Entity Framework и вызов context.dispose()
Когда следует вызывать DbContext.dispose()
со структурой сущностей?
-
Этот мнимый метод плох?
public static string GetName(string userId)
{
var context = new DomainDbContext();
var userName = context.UserNameItems.FirstOrDefault(x => x.UserId == userId);
context.Dispose();
return userName;
}
-
Это лучше?
public static string GetName(string userId)
{
string userName;
using(var context = new DomainDbContext()) {
userName = context.UserNameItems.FirstOrDefault(x => x.UserId == userId);
context.Dispose();
}
return userName;
}
-
Это даже лучше, то есть НЕ следует вызывать context.Dispose() при использовании using()?
public static string GetName(string userId)
{
string userName;
using(var context = new DomainDbContext()) {
userName = context.UserNameItems.FirstOrDefault(x => x.UserId == userId);
}
return userName;
}
Ответы
Ответ 1
На самом деле это два вопроса в одном:
- Когда я должен
Dispose()
из контекста?
- Какой должна быть продолжительность жизни моего контекста?
Ответы:
Никогда 1. using
является неявным Dispose()
в блоке try-finally
. Отдельный оператор Dispose
может быть пропущен, когда исключение возникает раньше. Кроме того, в большинстве распространенных случаев вообще не вызывать Dispose
(явно или явно) не вредно.
Смотрите, например Entity Framework 4 - продолжительность жизни/контекст контекста в приложении winform. Короче говоря: продолжительность жизни должна быть "короткой", статический контекст плохой.
1 Как отмечают некоторые люди, исключением из этого правила является случай, когда контекст является частью компонента, который реализует сам IDisposable
и разделяет его жизненный цикл. В этом случае вы бы вызвали context.Dispose()
в методе Dispose
компонента.
Ответ 2
Я следил за хорошими учебниками, чтобы использовать EF, и они не нарушают контекст.
Мне было немного любопытно, и я заметил, что даже уважаемый Microsoft VIP не нарушает контекст. Я обнаружил, что вам не нужно удалять dbContext в нормальной ситуации.
Если вам нужна дополнительная информация, вы можете прочитать этот пост в блоге, в котором кратко объясняется, почему.
Ответ 3
Еще лучше:
public static string GetName(string userId)
{
using (var context = new DomainDbContext()) {
return context.UserNameItems.FirstOrDefault(x => x.UserId == userId);
}
}
Не нужно возвращать результат извне области using
; просто верните его немедленно, и вы все равно получите желаемое поведение.
Ответ 4
Вы можете определить контекст вашей базы данных как поле класса и реализовать IDisposable
. Что-то вроде ниже:
public class MyCoolDBManager : IDisposable
{
// Define the context here.
private DomainDbContext _db;
// Constructor.
public MyCoolDBManager()
{
// Create a new instance of the context.
_db = new DomainDbContext();
}
// Your method.
public string GetName(string userId)
{
string userName = _db.UserNameItems.FirstOrDefault(x => x.UserId == userId);
return userName;
}
// Implement dispose method.
// NOTE: It is better to follow the Dispose pattern.
public void Dispose()
{
_db.dispose();
_db = null;
}
}
Ответ 5
Я бы использовал вариант 3; используя using()
, вы автоматически разместите контекст для вас. Вариант 2 плох. Вариант 1 также может быть в порядке, но вариант 3 кажется более читаемым.
Ответ 6
Как упоминал Даниэль, вам не нужно избавляться от dbContext.
Из статьи:
Несмотря на то, что он реализует IDisposable, он только реализует его, поэтому в некоторых особых случаях вы можете вызвать Dispose в качестве меры предосторожности. По умолчанию DbContext автоматически управляет соединением для вас.
Итак:
public static string GetName(string userId) =>
new DomainDbContext().UserNameItems.FirstOrDefault(x => x.UserId == userId);