2014-02-19 2 views
10

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

+0

Как вы используете сейчас? Обычно я использую контекст в используемом блоке. – GrandMasterFlush

+0

В настоящее время он не использует блок. – Abhinay

+1

Храните его без использования, использование будет уничтожать потенциальные потоки, запущенные из него, поскольку контекст будет, возможно, удален до того, как он достигнет конца запущенной формы потока. –

ответ

24

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

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

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

(полезная reference.)

+4

Вопрос о GC и IDisposable цели, или конкретно о DbContext? –

+0

Вопрос специфичен для 'DbContext', но ответ заключается в том, что' DbContext' восприимчив к точно такой же лучшей практике, как и любой другой 'IDisposable', по тем же причинам, что и каждый другой' IDisposable' - следовательно, основной ответ , –

+2

Это до OP и тех, кто поддержал этот ответ. Я не вижу ничего конкретного для DbContext здесь. Никакое объяснение того, какие ресурсы должны быть выпущены. –

2

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

Следовательно, ИМХО вопрос о том, нужно ли «явно» распоряжаться объектом, не имеет значения. Если он просит избавиться - в силу осуществления IDisposable - его следует утилизировать.

7

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

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

так он получил automaitaclly, расположенный

+0

Если мы будем использовать этот подход, как мы можем издеваться над DBContext для написания модульных тестов? – Mitch

+0

Посмотрите репозиторий и образец рабочего шаблона http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository- и-unit-of-work-patterns-in-as-asp-net-mvc-application – Chris

+0

Что делать, если я хочу использовать контекст в классе? (создать его в конструкторе - как и где его закрыть?) – Estevez

2

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

Пример примера: первый пример - вызов и оценка его в операторе using, а второй - его после.(Первый ONS бежит, второй один бросает ошибку 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); 
} 

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

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); 
} 

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

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

Внеклассное чтение полночь:

  1. http://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext.html#.U6WdzrGEeTw
  2. https://msdn.microsoft.com/en-us/data/jj729737.aspx
Смежные вопросы