I just set up AutoFac in my MVC project and set my EF DbContext to InstancePerRequest
. Until now DbContext has been a static singleton. It seems that AutoFac's "request" scope is not really the entire request. I'm getting the error message:
The operation cannot be completed because the DbContext has been disposed.
Much like some other questions.
I would expect the context to be disposed after the entire request has been handled, but the exception is showing up when I try to access lazily loaded properties in views or return statements.
An example of the problem:
[HttpGet]
public JsonResult GetLotoLockNumbers(int permitId)
{
var lockNums = lockService.FindLotoLockNumbers(permitId);
// this line throws an exception because... (go to last line)
return Json(string.Join(", ", lockNums), JsonRequestBehavior.AllowGet);
}
public IEnumerable<string> FindLotoLockNumbers(int permitId)
{
// returns an attached entity
var permit = Repository.GetDBEntityWithId<PermPermit>(permitId);
return GetLotoLockNumsForPermit(permit).AsEnumerable();
}
private IEnumerable<string> GetLotoLockNumsForPermit(PermPermit permit, int? configLockItemId = null)
{
// lazily accesses virtual properties
var lotoLockItems = permit.permitSections.SelectMany(section => section.childs.Where(
(sectionItem) => IsLotoLockSectionItem(sectionItem, configLockItemId))).AsEnumerable();
return lotoLockItems.SelectMany(item => LotoLockHelper.ParseLockNums(item.value)).AsEnumerable();
}
private bool IsLotoLockSectionItem(PermPermitSectionItem item, int? configLockItemId = null)
{
// ...the context has been exposed when this line gets lazily executed
return lockItemIds.Contains(item.confSectionItem.id);
}
My favourite solution would be if I could simply extend the scope of the context so that it lasts for the whole request (a singleton
is not ok). Otherwise, I'll have to make changes throughout the code to make sure that everything is loaded before controller actions return
.