";操作无法完成,因为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>> 的参数

为什么即使禁用了延迟加载,我也会得到一个处置异常?

";操作无法完成,因为DbContext已被“释放”;禁用延迟加载的异常

懒惰和急切的加载与加载与查询相关的实体(例如导航属性和集合)有关,而不是与加载查询本身的内容有关。

从存储库返回的IQuerable<EntityAddress>—无论您是否启用了延迟加载—将不会在服务器上运行查询,直到它被枚举(无论是通过在foreach循环中获取枚举器、在其上调用Enumerable.ToList<TSource>,还是将其传递到对Controller.View的调用中以进行下游呈现)。

在这种情况下出现异常的原因是Controller.View不会立即呈现视图(因此不会立即枚举查询)。它所做的只是构造一个ViewResult的实例,该实例保留模型参数(查询对象),直到MVC稍后在处理完上下文后呈现视图。

如果要将查询结果传递给视图,有两个选项:

  1. 将数据库上下文的寿命延长到控制器的寿命
  2. 在数据库上下文被释放之前,在IQuerable<EntityAddress>上调用Enumerable.ToList<EntityAddress>,并使用生成的List<EntityAddress>而不是IQuerable<EntityAddress>