“操作无法完成,因为DbContext已被处理”异常并且禁用了延迟加载

时间:2013-08-15 20:59:15

标签: c# asp.net-mvc-3 entity-framework-5

假设:

    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>>

类型的参数

为什么即使在禁用延迟加载后我也会收到处理异常?

1 个答案:

答案 0 :(得分:7)

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

从您的存储库返回的IQuerable<EntityAddress> - 无论您是否启用了延迟加载 - 在枚举之前都不会在服务器上运行查询(无论是通过在foreach循环中获取枚举数,在其上调用Enumerable.ToList<TSource>,或将其传递给Controller.View进行下游渲染调用。)

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

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

  1. 将数据库上下文的生命周期延长到控制器的生命周期
  2. 在放置数据库上下文之前调用IQuerable<EntityAddress>上的Enumerable.ToList<EntityAddress>,并使用生成的List<EntityAddress>代替IQuerable<EntityAddress>