В LINQ-SQL обернуть DataContext оператором using - плюсы и минусы

Может ли кто-нибудь высказать свое мнение о плюсах и минусах между переносом DataContext в оператор using или нет в LINQ-SQL с точки зрения таких факторов, как производительность, использование памяти, простота кодирования, правильные действия и т. Д.

Обновление: В одном конкретном приложении я испытал, что без обертывания DataContext в блоке using объем использования памяти продолжал расти, поскольку живые объекты не были выпущены для GC. Как и в примере ниже, если я держу ссылку на объект List of q и получаю доступ к объектам q, я создаю граф объектов, который не выпущен для GC.

DataContext с использованием

    using (DBDataContext db = new DBDataContext())
    {
        var q = 
            from x in db.Tables
            where x.Id == someId
            select x;

        return q.toList();
    }

DataContext без использования и сохранения

  DBDataContext db = new DBDataContext()
  var q = 
        from x in db.Tables
        where x.Id == someId
        select x;

    return q.toList(); 

Спасибо.


person hIpPy    schedule 18.02.2010    source источник
comment
Похоже на дубликат: stackoverflow.com/questions/821574/   -  person devuxer    schedule 19.02.2010
comment
Хотелось бы узнать влияние на память.   -  person hIpPy    schedule 19.02.2010
comment
аналогично stackoverflow.com/questions/821574/, спасибо DanM.   -  person hIpPy    schedule 24.02.2010
comment
Это может выглядеть глупо, но ... Как мне получить DBDataContext? Я создаю всю базу в EF и теперь пытаюсь получить доступ к данным. Все, что у меня есть, это DataContext context = new DataContext(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString());   -  person Michel Ayres    schedule 19.02.2013


Ответы (5)


Создание DataContext может быть дорогостоящим по сравнению с другими вещами. Однако, если вы закончили с этим и хотите, чтобы соединения были закрыты как можно скорее, это сделает это, также выпуская все кешированные результаты из контекста. Помните, что вы создаете его, несмотря ни на что, в этом случае вы просто даете сборщику мусора знать, что есть еще бесплатные вещи, от которых нужно избавиться.

DataContext создан как объект кратковременного использования, используйте его, выполните единицу работы, уйдите ... именно это вы и делаете с using.

Итак, преимущества:

  • Более быстрые закрытые соединения
  • Освободить память от удаления (кэшированные объекты в содержимом)

Оборотная сторона - больше кода? Но это не должно быть сдерживающим фактором, вы здесь правильно используете using.

Посмотрите здесь ответ Microsoft: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2625b105-2cff-45ad-ba29-abdd763f74fe

Краткая версия, если вам нужно использовать _2 _ / _ 3_:

Краткий ответ; нет, не обязательно, но следует ...

person Nick Craver    schedule 18.02.2010
comment
По-видимому, мы по-разному слышали о сложности создания DataContext. - person James Curran; 19.02.2010
comment
@James - Хотя он не такой тяжелый, по сравнению с другими вещами, в моем текущем приложении это самый тяжелый элемент, который нужно раскручивать, он легкий, но все же тяжелее, чем ваш средний объект. - person Nick Craver; 19.02.2010

Ну, это IDisposable, так что я думаю, это неплохая идея. Люди из MSFT сказали, что они сделали DataContexts как можно более легкими, чтобы вы могли создавать их безрассудно, так что вы, вероятно, не сильно выиграете ...

person James Curran    schedule 18.02.2010
comment
Это ответ, который я получил, задав аналогичный вопрос в другом месте. В принципе, это не больно и может помочь, но, вероятно, нет. - person mark123; 19.02.2010
comment
@ mark123: за одним исключением, все IDisposable, которые вы создаете, используете и завершаете в рамках одного метода, должны использоваться в блоке using. В противном случае авторы не стали бы реализовывать IDisposable. - person John Saunders; 06.03.2010
comment
Я согласен. Всегда старайтесь делать это правильно. У меня возникла небольшая проблема, когда я пытался выяснить, как использовать блок using вместе с разрешением контейнеру IoC (Castle Windsor) создавать экземпляры элементов из репозитория. Подчеркивая эту проблему, мне сказали, что контейнер IoC обрабатывает Dispose (). Я надеюсь, что это правильно, потому что это действительно имеет смысл. - person mark123; 07.03.2010

  1. Первый раз DataContext получит объект из БД.
  2. В следующий раз, когда вы запустите запрос для получения того же объекта (с теми же параметрами): вы увидите запрос в профилировщике, но ваш объект в DataContext не будет заменен новым из БД !!

Не говоря уже о том, что за каждым DataContext стоит карта идентичности всех объектов, которые вы запрашиваете из БД (вы не хотите, чтобы это было постоянно).

Вся идея DataContext - это Единица работы с Оптимистическим параллелизмом. Используйте его для короткой транзакции (только одна отправка) и удалите.

Лучший способ не забыть об утилизации - использовать ().

person Vladimir Kojic    schedule 19.03.2010

Я зависит от сложности вашего уровня данных. Если каждый вызов представляет собой простой одиночный запрос, то каждый вызов можно обернуть в Использование как в вашем вопросе, и это будет нормально.

Если, с другой стороны, ваш уровень данных может ожидать несколько последовательных вызовов от бизнес-уровня, вам придется многократно создавать / удалять DataContext для каждой более крупной последовательности вызовов. не идеал.

Я создал объект уровня данных как IDisposible. Когда он создается, создается DataContext (или, на самом деле, после первого вызова метода), а когда объект уровня данных удаляется, он закрывается и удаляет DataContext.

вот как это выглядит:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace PersonnelDL
{
    public class PersonnelData : IDisposable
    {
        #region DataContext management
        /// <summary>
        /// Create common datacontext for all data routines to the DB
        /// </summary>
        private PersonnelDBDataContext _data = null;
        private PersonnelDBDataContext Data
        {
            get
            {
                if (_data == null)
                {
                    _data = new PersonnelDBDataContext(ConfigurationManager.ConnectionStrings["PersonnelDB"].ToString());
                    _data.DeferredLoadingEnabled = false; // no lazy loading
                    //var dlo = new DataLoadOptions(); // dataload options go here
                }
                return _data;
            }
        }

        /// <summary>
        /// close out data context
        /// </summary>
        public void Dispose()
        {
            if (_data != null)
                _data.Dispose();
        }
        #endregion

        #region DL methods
        public Person GetPersonByID(string userid)
        {
            return Data.Persons.FirstOrDefault(p => p.UserID.ToUpper().Equals(userid.ToUpper()));
        }

        public List<Person> GetPersonsByIDlist(List<string> useridlist)
        {
            var ulist = useridlist.Select(u => u.ToUpper().Trim()).ToList();
            return Data.Persons.Where(p => ulist.Contains(p.UserID.ToUpper())).ToList();
        }

        // more methods...
        #endregion
    }
}
person Mike Jacobs    schedule 19.02.2010

В одном конкретном приложении я испытал, что без упаковки блока DataContext в using объем используемой памяти продолжал расти, поскольку живые объекты не были выпущены для сборки мусора. Как и в примере ниже, если я держу ссылку на объект List<Table> и получаю доступ к объектам q, я создаю граф объектов, который не выпущен для GC.

DBDataContext db = new DBDataContext()
var qs = 
    from x in db.Tables
    where x.Id == someId
    select x;

return qs.toList();

foreach(q in qs)
{
    process(q);
    // cannot dispose datacontext here as the 2nd iteration 
    // will throw datacontext already disposed exception 
    // while accessing the entity of q in process() function
    //db.Dispose();
}

process(Table q)
{
    // access entity of q which uses deferred execution
    // if datacontext is already disposed, then datacontext 
    // already disposed exception is thrown
}

В этом примере я не могу удалить текст данных, потому что все экземпляры Table в переменной списка qs ** используют один и тот же текст данных. После Dispose() доступ к объекту в process(Table q) вызывает исключение, которое уже удалено из контекста данных.

Для меня уродливым занятием было удалить все ссылки на сущности для q объектов после цикла foreach. Лучше, конечно, использовать оператор using.

Исходя из моего опыта, я бы сказал, что используйте оператор using.

person hIpPy    schedule 06.03.2010