2010-02-18 2 views
22

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

Update: в одном конкретном приложении, я испытал, что без обертывания DataContext в использовании блока, объем используемой памяти хранится на увеличение как живые объекты не были выпущены для GC. Как и в примере ниже, если я держу ссылку на объект «Список объектов 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(); 

Спасибо.

+2

Выглядит как дубликат: http://stackoverflow.com/questions/821574/c-linq-to-sql-should-datacontext-be-disposed-using-idisposable/821595 – devuxer

+0

Хотелось бы узнать влияние на память. – hIpPy

+0

похож на http://stackoverflow.com/questions/821574/c-linq-to-sql-should-datacontext-be-disposed-using-idisposable/821595, благодаря DanM. – hIpPy

ответ

12

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

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

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

  • Quicker закрытые соединения
  • Свободная память от Dispose (кэшированных объектов в содержании)

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

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

короткая версия, если вам нужно использовать using/.Dispose():

Короткий ответ; нет, вы не должны, но вы должны ...

+2

По-видимому, мы слышали разные вещи о сложности создания DataContext. –

+0

@James - Хотя это не так уж и тяжело, ** по отношению к другим вещам **, в моем текущем приложении это самый тяжелый предмет, который закручивается, он легкий, но все же тяжелее, чем ваш средний объект. –

5

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

+0

Это ответ, который я получил, задав аналогичный вопрос в другом месте.В принципе, это не больно и может помочь, но, вероятно, нет. – mark123

+3

@ mark123: за единственным исключением, все IDisposable, которые вы создаете, используете и заканчиваете с помощью одного метода, должны потребляться в блоке 'using'. В противном случае авторы не захотели бы реализовать 'IDisposable'. –

+0

Я согласен. Всегда старайтесь делать это правильно. У меня возникла небольшая проблема, когда я пытался выяснить, как использовать блок, а также позволить контейнеру IoC (Castle Windsor) создавать объекты из репозитория. Подчеркивая эту проблему, мне сказали, что контейнер IoC обрабатывает Dispose(). Надеюсь, это правильно, поскольку это действительно имеет смысл. – mark123

4

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

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

Что я сделал, это создать объект Data Layer как IDisposible. Когда он создается, создается DataContext (или действительно, как только первый вызов метода выполняется), и когда объект Data Layer находится, он закрывает и удаляет 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 
    } 
} 
1

В одном конкретном приложении, я испытал, что без оборачивания DataContext в using блок, объем используемой памяти хранится на увеличение как живые объекты не были выпущены для GC. Как и в примере ниже, если я держу ссылку на объект 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 
} 

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

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

Что касается моих впечатлений, я бы сказал, используя заявление using.

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

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

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

Лучший способ не забыть утилизировать с помощью().

Смежные вопросы