“The operation cannot be completed because the DbContext has been disposed” exception with lazy load disabled

允我心安 提交于 2019-12-19 09:49:23

问题


Given:

    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 is disposable and handles disposal of my DbContext. It also disables lazy loading in the constructor:

    public UnitOfWork()
    {
        _dbContext.Configuration.LazyLoadingEnabled = false;
        Repository = new GenericRepository<MyEntities>(_dbContext);            
    }

    public void Dispose()
    {
        Repository.Dispose();
    }

And the Find<EntityAddress>() implementation works out to:

_dbContext.Set<EntityAddress>().Where(predicate) where predicate is a parameter of type Expression<Func<EntityAddress, bool>>

Why do I get a disposal exception even after I disabled lazy loading?


回答1:


Lazy and eager loading have to do with when entities related to your query (e.g. navigation properties and collections) are loaded, not when the contents of the query itself are loaded.

The IQuerable<EntityAddress> returned from your repository—whether or not you have lazy loading enabled—will not run the query on the server until it's enumerated (whether that's by getting an enumerator in a foreach loop, calling Enumerable.ToList<TSource> on it, or passing it into a call to Controller.View for downstream rendering).

The reason you get an exception in this case is because Controller.View does not immediately render the view (and therefore does not immediately enumerate the query). All it does is construct an instance of ViewResult that holds onto the model parameter (your query object) until MVC does render the view later on, after you've disposed your context.

If you want to pass query results to a view, you have two options:

  1. Extend the life of the database context to the lifetime of the controller
  2. Call Enumerable.ToList<EntityAddress> on the IQuerable<EntityAddress> before the database context is disposed, and use the resulting List<EntityAddress> instead of the IQuerable<EntityAddress>.


来源:https://stackoverflow.com/questions/18261732/the-operation-cannot-be-completed-because-the-dbcontext-has-been-disposed-exce

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!