В 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();
Спасибо.
Ответы
Ответ 1
DataContext может быть дорогим для создания, по сравнению с другими вещами. Однако, если вы закончите с этим и хотите, чтобы соединения были закрыты как можно скорее, это сделает это, высвободив любые кешированные результаты из контекста. Помните, что вы создаете его, несмотря ни на что, в этом случае вы просто позволяете сборщику мусора узнать, есть ли более свободные вещи, чтобы избавиться.
DataContext превращается в объект короткого использования, использует его, получает часть выполняемой работы, вытаскивает... именно то, что вы делаете при использовании.
Итак, преимущества:
- Более быстрые закрытые соединения
- Свободная память из распоряжения (кешированные объекты в контенте)
Даунсайд - больше кода? Но это не должно быть сдерживающим фактором, вы используете здесь using
.
Посмотрите на ответ Microsoft: http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2625b105-2cff-45ad-ba29-abdd763f74fe
Короткий вариант, если вам нужно использовать using
/.Dispose()
:
Короткий ответ; нет, вам это не нужно, но вы должны...
Ответ 2
Ну, это a IDisposable
, поэтому я думаю, это не плохая идея. Люди в MSFT сказали, что они сделали DataContexts максимально легкими, чтобы вы могли создавать их с безрассудным отказом, поэтому вы, вероятно, не получаете много, хотя.....
Ответ 3
- Впервые DataContext получит объект из БД.
- В следующий раз, когда вы запускаете запрос для получения одного и того же объекта (такие же параметры): вы увидите запрос в профилировщике, но ваш объект в DataContext не будет заменен новым из DB!!
Не говоря уже о том, что за каждым DataContext - это идентификационная карта всех объектов, которые вы запрашиваете из БД (вы не хотите держать это в стороне).
Вся идея DataContext Единица работы с Оптимистичной Concurrency.
Используйте его для короткой транзакции (только для отправки) и утилизации.
Лучший способ не забыть dispose - использовать().
Ответ 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
}
}
Ответ 5
В одном конкретном приложении я испытал это, не обернув блок DataContext
in 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
.