";操作无法完成,因为DbContext已被“释放”;禁用延迟加载的异常
本文关键字:释放 延迟加载 异常 已被 因为 操作 quot DbContext | 更新日期: 2023-09-27 18:27:47
给定:
public ActionResult List()
{
using (var unitOfWork = new UnitOfWork())
{
var result = unitOfWork.Repository.Find<EntityAddress>(a => a.PostalCode == "80001");
//return View(result.ToList());//NO Exception raised with ToList()
return View(result);//EXCEPTION RAISED IN VIEW DURING ITERATION
}
}
UnitOfWork
是一次性的,并处理我的DbContext的处理。它还禁用构造函数中的延迟加载:
public UnitOfWork()
{
_dbContext.Configuration.LazyLoadingEnabled = false;
Repository = new GenericRepository<MyEntities>(_dbContext);
}
public void Dispose()
{
Repository.Dispose();
}
Find<EntityAddress>()
的实现结果是:
_dbContext.Set<EntityAddress>().Where(predicate)
,其中谓词是类型为Expression<Func<EntityAddress, bool>>
的参数
为什么即使禁用了延迟加载,我也会得到一个处置异常?
懒惰和急切的加载与加载与查询相关的实体(例如导航属性和集合)有关,而不是与加载查询本身的内容有关。
从存储库返回的IQuerable<EntityAddress>
—无论您是否启用了延迟加载—将不会在服务器上运行查询,直到它被枚举(无论是通过在foreach
循环中获取枚举器、在其上调用Enumerable.ToList<TSource>
,还是将其传递到对Controller.View
的调用中以进行下游呈现)。
在这种情况下出现异常的原因是Controller.View
不会立即呈现视图(因此不会立即枚举查询)。它所做的只是构造一个ViewResult
的实例,该实例保留模型参数(查询对象),直到MVC稍后在处理完上下文后呈现视图。
如果要将查询结果传递给视图,有两个选项:
- 将数据库上下文的寿命延长到控制器的寿命
- 在数据库上下文被释放之前,在
IQuerable<EntityAddress>
上调用Enumerable.ToList<EntityAddress>
,并使用生成的List<EntityAddress>
而不是IQuerable<EntityAddress>