Требуется контекстный объект для размещения объекта Entity Framework

Мы используем структуру сущностей для связи с базой данных в наших методах службы WCF, недавно мы запускаем инструмент проверки кода в нашем сервисном коде. Как обычно, у нас было много предложений по обзору с помощью инструмента, и многие комментарии к обзору предлагали избавиться от объекта контекста Entity Framework. Итак, мой вопрос заключается в том, что я использую объект контекста Entity Framework внутри метода, и как только я выхожу из метода, GC не очищает объект контекста? нам нужно явно удалять объект контекста?

Ответ 1

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

Вам не нужно избавляться от него, потому что GC в конечном итоге соберет его, но GC не детерминирован: вы никогда не знаете, когда будет "в конце концов". Пока он не будет размещен, он будет удерживать ресурсы, которые не используются - например, он может все еще иметь открытое соединение с базой данных. Эти ресурсы не освобождаются до тех пор, пока GC не будет запущен, если вы не будете утилизировать вручную. В зависимости от конкретных деталей вы можете обнаружить, что у вас есть излишне заблокированные сетевые ресурсы, доступ к файлам, и вы наверняка сохраните больше памяти, чем вам нужно.

Есть и еще один потенциальный риск: когда вы распоряжаетесь объектом вручную, GC обычно не нужно вызывать Finalizer на этом объекте (если таковой имеется). Если вы оставите GC для автоматического удаления объекта с помощью Finalizer, он поместит объект в очередь Finalizer и автоматически продвинет объект к следующему поколению GC. Это означает, что объект с финализатором всегда будет зависать на порядки дольше, чем нужно, прежде чем он будет GCed (поскольку последовательные поколения GC собираются реже). DbContext, вероятно, попадет в эту категорию, поскольку базовое соединение с базой данных будет неуправляемым кодом.

(Полезно ссылка.)

Ответ 2

Я думаю, что лучший подход заключается в его кодировании в операторе using

using(var cx = new DbContext())
{
  //your stuff here
}

поэтому он получил автоматическое расположение

Ответ 3

В общем, если что-то реализует IDisposable, это хорошая идея (TM), чтобы явным образом распоряжаться ею, когда вы закончите. Это особенно верно, если вы не владеете реализацией указанного объекта; вы должны рассматривать это как черный ящик в этом случае. Кроме того, даже если это не обязательно "нужно", чтобы избавиться от него сейчас, оно может быть в будущем.

Поэтому IMHO вопрос о том, нужно ли вам "явно" распоряжаться объектом, не имеет значения. Если он просит избавиться - в силу реализации IDisposable - его следует утилизировать.

Ответ 4

Рекомендуемая вещь, связанная с DBContext, заключается в том, чтобы вообще не использовать ее (это правило является исключением из правила в большинстве случаев), хотя это одноразовый объект.

Пример проблемы. Первый пример - это вызов и оценка его в операторе using, а второй - после него. (первые запускаются, вторая вызывает ошибку The operation cannot be completed because the DbContext has been disposed.)

List<Test> listT;
using (Model1 db = new Model1())
{
    listT = db.Tests.ToList(); //ToList Evaluates
}
foreach (var a in listT)
{
    Console.WriteLine(a.value);
}

IEnumerable<Test> listT1;
using (Model1 db = new Model1())
{
    listT1 = db.Tests;
}
foreach (var a in listT1) //foreach evaluates (but at wrong time)
{
    Console.WriteLine(a.value);
}

То же самое происходит в

IEnumerable<Test> listT1;
Model1 db = new Model1();
listT1 = db.Tests;
db.Dispose();
foreach (var a in listT1) //foreach evaluates (but at wrong time)
{
    Console.WriteLine(a.value);
}

В то время как вы не открываете соединение вручную, вы можете безопасно использовать

IEnumerable<Test> listT1;
Model1 db = new Model1();
listT1 = db.Tests;
foreach (var a in listT1) //foreach evaluates (but at wrong time)
{
    Console.WriteLine(a.value);
}

и никогда не удаляйте. поскольку он будет заботиться о себе при большинстве обстоятельств, как это он и сделал.

Теперь вы должны открыть соединение силой, тогда контекст не будет автоматически закрывать его, когда передача будет выполнена, поскольку она не знает, когда и затем вы должны/должны располагать объект или закрывать соединение и держать объект нераскрытым.

Дополнительная полуночи:

Ответ 5

Нет необходимости явно удалять DbContext.

Это старое удержание инструментов pre-DbContext. DbContext - это управляемый код, который самостоятельно поддерживает соединения с базой данных. Почему кувалда это? Что за спешка? Почему бы просто не позволить сборщику мусора выбрать наилучшее время для очистки, когда машина простаивает или нуждается в памяти? Также обратитесь к этому сообщению: https://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext/

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

public class DataTools
{
    private AppContext _context;
    protected AppContext Context => _context ?? (_context = new AppContext());
}

pubic class YourApp : DataTools
{
    public void DoLotsOfThings()
    {
        var = Context.SomeTable.Where(s => s.....);
        var stuff = GetSomeThing();
       foreach(){}
    }

    Public string GetSomething()
    {
        return Context.AnotherTable.First(s => s....).Value;
    }
}