В LINQ-SQL оберните DataContext, используя инструкцию - pros cons

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

Обновление. В одном конкретном приложении я испытал, что, не обертывая 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();

Спасибо.

5 ответов

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

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

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

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

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

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

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

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


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


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

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

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

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


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

Если, с другой стороны, ваш уровень данных может ожидать множественные последовательные вызовы из бизнес-уровня, вы можете повторно создавать/удалять 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
 }
}
</string></person>


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

<code>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
}
</code>

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

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

Насколько мне известно, я бы использовал инструкцию <code>using.

licensed under cc by-sa 3.0 with attribution.