DbContexts предназначены для кратковременного использования.Самая первая инициализация и использование DbContext представляет собой ускорение затрат для разрешения сопоставлений сущностей, но помимо этого контекст может быть ограничен отдельными вызовами или наборами вызовов.Ваш код будет работать нормально, и пока ваше хранилище будет удалено, dbContext будет очищен.С этим подходом есть подводные камни, хотя в процессе созревания продукта легко забыть утилизировать что-либо, и эти DbContexts могут поглотить немало памяти, если они долговечны.
Чтобы избежать проблем ссущности, которые становятся отключенными от своего DbContext, сущность никогда не должна выходить за рамки своего DbContext.Если это произойдет, вы столкнетесь с ошибками, например, при запуске отложенной загрузки.
Например, допустим, у меня есть метод в контроллере или что-то подобное, что делает что-то вроде этого: (Примечание: я не защищаюкогда-либо возвращать сущности в представление, но, например, ради ...)
public ActionResult View(long accountNumber)
{
BankAccount bankAccount;
using (var repo = new RepoBankAccount())
{
bankAccount = repo.ViewBankAccount(accountNumber);
}
return new View(bankAccount);
}
Репо будет ликвидировано, и если банковский счет либо не имеет ссылок, либо все ссылки загружены, этот вызов будет работатьпросто хорошо.Однако при наличии отложенного вызова загрузки метод контроллера завершится неудачно, так как был удален DbContext, связанный с банковским счетом.
Это можно компенсировать, обеспечив возврат в пределах области использования блока:
public ActionResult View(long accountNumber)
{
using (var repo = new RepoBankAccount())
{
BankAccount bankAccount = repo.ViewBankAccount(accountNumber);
return new View(bankAccount);
}
}
Чтобы избежать подобных проблем, обычно лучше создать классы моделей представлений POCO, чтобы заполнить их в рамках DbContext из сущностей, а затем вернуть эти модели представлений.Неудивительно, что ленивая загрузка загружается и т. Д.
Когда это действительно начинает рушиться, это когда вы хотите координировать такие вещи, как обновления между сущностями, чтобы гарантировать, что обновления фиксируются или откатываются вместе.Каждый из ваших классов репо будет иметь отдельные экземпляры DbContext.
Первый подход по умолчанию, с которым можно ознакомиться для решения этой проблемы, - это внедрение зависимостей и инверсия управления, в частности контейнер IoC, такой как Autofac , Unity, Ninject или Castle Windsor.Используя их, вы можете сделать так, чтобы ваши классы репозитория принимали зависимость от DbContext, и они могли охватывать один экземпляр зависимости в течение жизни.(например, в соответствии с HTTP-запросом). Таким образом, ссылки на все ваши репозитории в одном сеансе будут предоставлены в одном экземпляре DbContext.Вызов SaveChanges () попытается зафиксировать все ожидающие изменения.
Лучшим шаблоном является шаблон «Единица работы», где область действия DbContext перемещается за пределы репозитория, и каждый репозиторий либо содержит ссылку наDbContext, или можете найти его.(аналогично тому, как работает шаблон IoC) Преимущество шаблонов UoW заключается в том, что вы можете передать управление фиксацией / откатом потребителю репозиториев. Я поощряю использование DhContextScope от Mehdime, поскольку это устраняет необходимость передавать ссылки наUOW / DbContext. Mehdime DbContextScope (EF6 original github ) EFCore поддерживаемый порт