我刚刚在我的MVC项目中设置了AutoFac,并将EF DbContext设置为InstancePerRequest
。到目前为止,DbContext一直是静态单例。似乎AutoFac的“请求”范围实际上并不是整个请求。我收到错误消息:
由于已处理DbContext,因此无法完成操作。
我希望在处理完整个请求之后处理上下文,但是当我尝试访问视图或return语句中的延迟加载属性时,会出现异常。
问题的一个示例:
[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);
}
我最喜欢的解决方案是,如果我可以简单地扩展上下文的范围,使其在整个请求中都持续(singleton
并不可行)。否则,我将不得不在整个代码中进行更改,以确保在控制器动作return
之前已加载所有内容。
答案 0 :(得分:0)
我对AutoFac完全不对。这里代码中的问题不是查询的执行被推迟,而是lockItemIds
对象是被推迟执行的IEnumerable
对象。我加载了列表,并使用旧的上下文将其存储在静态变量中,却没有意识到它没有立即执行。
AutoFac的请求范围很完美。
教训是:使用调试器确保您确切地知道引起问题的对象并检查静态变量。