Подтвердить что ты не робот

Entity Framework и вызов context.dispose()

Когда следует вызывать DbContext.dispose() со структурой сущностей?

  1. Этот мнимый метод плох?

    public static string GetName(string userId)
    {
        var context = new DomainDbContext();
        var userName = context.UserNameItems.FirstOrDefault(x => x.UserId == userId);
        context.Dispose();
        return userName;
    }
    
  2. Это лучше?

    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;
    }
    
  3. Это даже лучше, то есть НЕ следует вызывать 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;
    }
    
4b9b3361

Ответ 1

На самом деле это два вопроса в одном:

  1. Когда я должен Dispose() из контекста?
  2. Какой должна быть продолжительность жизни моего контекста?

Ответы:

  1. Никогда 1. using является неявным Dispose() в блоке try-finally. Отдельный оператор Dispose может быть пропущен, когда исключение возникает раньше. Кроме того, в большинстве распространенных случаев вообще не вызывать Dispose (явно или явно) не вредно.

  2. Смотрите, например 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);