Должен ли контекст Framework Entity использовать в использовании Statement?
Объектный объект Entity Framework реализует метод Dispose(), который "Освобождает ресурсы, используемые контекстом объекта". Что он делает на самом деле? Может быть, это плохо, чтобы всегда использовать его в использовании {} заявления? Я видел, что он используется как с инструкцией using, так и без нее.
Я специально использую контекст EF из метода службы WCF, создаю контекст, делаю некоторый linq и возвращаю ответ.
РЕДАКТИРОВАТЬ: Кажется, что я не единственный, кто задается вопросом об этом. Другой вопрос - это то, что действительно происходит внутри метода Dispose(). Некоторые говорят, что он закрывает соединения, и в некоторых статьях говорится, что нет. Какая сделка?
Ответы
Ответ 1
Если вы создаете контекст, вы должны утилизировать его позже. Если вы должны использовать инструкцию using
, зависит от времени жизни контекста.
-
Если вы создаете контекст в методе и используете его только в этом методе, вы действительно должны использовать оператор using
, потому что он дает вам обработку исключений без какого-либо дополнительного кода.
-
Если вы используете контекст в течение более длительного периода - это время жизни не связано временем выполнения метода - вы не можете использовать оператор using
, и вам нужно позвонить Dispose()
самостоятельно и позаботьтесь о том, чтобы вы всегда его называли.
Что делает Dispose()
для контекста объекта?
Я не смотрел на код, но, по крайней мере, я рассматриваю его, чтобы закрыть соединение с базой данных со своими базовыми сокетами или любыми ресурсами, которые использовали механизм транспорта.
Ответ 2
Так как вы не знаете, когда сборщик мусора размещает элемент, всегда полезно обертывать объекты, которые реализуют IDisposable в используемом блоке, если вы знаете, когда закончите с ним.
Ответ 3
Per Progamming Entity Framework: "Вы можете либо явно разместить объект ObjectContext, либо дождаться, когда сборщик мусора выполнит эту работу".
Короче говоря, в то время как оператор using не требуется, лучше всего, если вы знаете, что вы закончили использование ObjectContext, так как ресурс немедленно освобождается, а не ждет сбор мусора.
Ответ 4
EF5 и до версии
using { ...
// connecction open here.
...
context.Blogs.Add(blog);
context.SaveChanges(); // query etc now opens and immediately closes
...
context.Blogs.Add(blog);
context.SaveChanges(); // query etc now opens and immediately closes
}
EF6 и после версии
using {
// connecction open here.
...
context.Blogs.Add(blog);
context.SaveChanges();
// The underlying store connection remains open for the next operation
...
context.Blogs.Add(blog);
context.SaveChanges();
// The underlying store connection is still open
} // The context is disposed – so now the underlying store connection is closed
Ссылка: http://msdn.microsoft.com/en-us/data/dn456849#open5
Ответ 5
Всегда, если вы создаете экземпляр класса, который реализует IDisposable, тогда вы несете ответственность за вызов Dispose на нем. Во всех случаях, кроме одного, это означает использование блока.
Ответ 6
При размещении объекта ObjectContext располагаются другие принадлежащие ему объекты.
Включая такие вещи, как EntityConnection, которые обертывают фактическое соединение с базой данных, то есть обычно SqlConnection.
Итак, если 'SqlConnection открыт, он будет закрыт, когда вы разместите ObjectContext.
Ответ 7
Я действительно проверил эту вещь как для ADO.net, так и для EF v.6 и просмотрел соединения в таблице SQL
select * from sys.dm_exec_connections
Методы тестирования должны выглядеть так:
1) ADO.net с помощью
using(var Connection = new SqlConnection(conString))
{
using (var command = new SqlCommand(queryString, Connection))
{
Connection.Open();
command.ExecuteNonQueryReader();
throw new Exception() // Connections were closed after unit-test had been
//finished. Expected behaviour
}
}
2) ADO.net с использованием
var Connection = new SqlConnection(conString);
using (var command = new SqlCommand(queryString, Connection))
{
Connection.Open();
command.ExecuteNonQueryReader();
throw new Exception() // Connections were NOT closed after unit-test had been finished
finished. I closed them manually via SQL. Expected behaviour
}
1) EF с использованием.
using (var ctx = new TestDBContext())
{
ctx.Items.Add(item);
ctx.SaveChanges();
throw new Exception() // Connections were closed, as expected.
}
2) EF без использования
var ctx = new TestDBContext();
ctx.Items.Add(item);
ctx.SaveChanges();
throw new Exception() // Connections WERE successfully closed, as NOT expected.
Я не знаю, почему это так, но EF автоматически закрывает соединения. Также все шаблоны репозитория и UnitOfWork, которые используют EF, не используют использование. Это очень странно для меня, потому что DBContext - это одноразовый тип, но это факт.
Возможно, в Microsoft они сделали что-то новое для обработки?
Ответ 8
Я заметил (хотя и в одном приложении), что явное удаление вызывало исключения прерывания потока в mscorlib, которые были захвачены до кода приложения, но, по крайней мере, в моем случае, что привело к заметному результату. Не делали каких-либо существенных исследований по этому вопросу, но, вероятно, что-то стоит рассмотреть, если вы это делаете. Просто посмотрите свой вывод DEBUG, чтобы узнать, получаете ли вы тот же результат.
Ответ 9
Если Dispose закрывает соединение с DB, это плохая идея назвать его.
Например, в ADO.NET соединения находятся в пуле соединений и никогда не закрываются до истечения времени ожидания или пула приложений.