Почему никто не управляет DbContext после работы контроллера WebApi?

Мне известны различные учебники, а также полные примеры таргетинга WebApi и Entity Framework (даже от Microsoft), у которых есть контроллер WebApi:

public HttpResponseMessage GetInternet(int id) {
    var context = new InternetDbContext();
    var result =
       (from internet in context.Internets
        where internet.Id.Equals(id)
        select internet).FirstOrDefault();
    if(result != null)
       Request.CreateResponse(HttpStatusCode.OK, result);
}

Но когда я узнал о Entity Framework, как 2 года назад, каждый ресурс, который я нашел о структуре, указывал, насколько чрезвычайно важно УТИЛИТЬ DbContex в SHORTEST срок службы, например с 'using'. И в наши дни люди, похоже, не дерутся об утилизации чего-либо (их менеджеров, репозиториев, контейнеров DI...).

Я что-то упустил? Означает ли конец вызова API автоматически контекст? Или мне нужно использовать что-то вроде HttpRequestMessageExtensions.RegisterForDispose() из http://msdn.microsoft.com/en-us/library/dn153859(v=vs.118).aspx?

Ответ 1

Лично, когда я вижу, что тип реализует IDisposable, я почти уверен, что я буду использовать инструкцию using при работе с новыми экземплярами этого типа.

Когда переменная выходит за пределы области видимости (как в вашем случае с переменной context, выходящей из области видимости, когда выполнение возвращается из метода GetInternet), ее память, в конце концов, будет возвращена сборщиком мусора, но это не делает 't означает, что любые собственные обработчики (например, обработчики файлов или соединения с базой данных) будут закрыты, что может оказать очень серьезное негативное влияние на ваше приложение.

Итак, рассмотрите возможность обертывания IDisposable в конструкцию using:

using (var context = new InternetDbContext())
{
  // Your code goes here
}

Надеюсь, что это поможет.

Ответ 2

Иногда это плохая идея, чтобы избавиться от контекста. Например, у меня есть метод контроллера WebAPI2, например,

    [Route("Questionnaires")]
    public IEnumerable<Questionnaire> GetAllQuestionnaires()
    {
        NMQContext context = new NMQContext();
        return context.Questionnaires.AsEnumerable();
    }

Данные результата представляют собой список JSON, а Questionnaire - составной объект - он содержит объекты из нескольких таблиц базы данных. Если я обернул это "использованием", я получаю сообщение об ошибке, например

   "Message": "An error has occurred.",
   "ExceptionMessage": "The operation cannot be completed because the DbContext has been disposed.",

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

Ответ 3

Основной случай для using, независимо от способа выхода из него будет удален ваш DbContext;

public HttpResponseMessage GetInternet(int id) {
    using(var context = new InternetDbContext()) {
        var result =
           (from internet in context.Internets
            where internet.Id.Equals(id)
            select internet).FirstOrDefault();
        if(result != null)
           Request.CreateResponse(HttpStatusCode.OK, result);
    }
}

Ответ 4

Вы должны Dispose() вашего контекстного класса, поэтому используйте конструкцию using:

using (var context = new InternetDbContext())
{    
    // your code here, try/catch is auto-generated by the compiler
}

Ответ 5

Это потому, что они ошибаются. Не доверяйте коду других людей, особенно если это часть онлайн-учебника.

Ответ 6

Вы должны вызвать Dispose() или использовать using при работе с DbContext, но вы не должны.

Если вы хотите быть осторожнее, всегда используйте using или Dispose() но если вы хотите лучше понять реализацию EF DbContext, продолжайте читать.

Короче говоря, EF обычно знает, когда пора закрывать соединение, поэтому в большинстве случаев вызов или не вызов Dispose() дает тот же результат и не влияет на использование памяти или производительность, поскольку сборщик мусора будет обрабатывать это автоматически, в отличие от большинства классов IDisposable.

Но есть две основные причины, по которым вам следует DbContext using или вызов Dispose() специально для EF DbContext.

Во-первых, когда кто-то вручную открывает соединение с ObjectContext из DbContext, если вы не вызываете Dispose()/using вы можете оставить открытые соединения, так как эти соединения не управляются EF.

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

Эту статью обязательно прочитать.

Ответ 7

вы должны использовать магическое ключевое слово "using". он будет автоматически размещаться.

 using (var context = new DBContext())
 {    
  //code here
 }