2

我有一个直接调用的控制器操作,但会引发此错误:

The operation cannot be completed because the DbContext has been disposed.

我只在网上找到了关于延迟执行的解决方案,但我认为这不适用于这里,因为我在任何地方使用上下文(在这种情况下)我都会调用.ToList()or 或.FirstOrDefault(). 这是我的代码:

控制器内容

    private IUnitOfWork UnitOfWork;
    public MyFavouritesController(
        IAccountServices accountServices,
        IUnitOfWork unitOfWork
        )
    {
        AccountServices = accountServices;
        UnitOfWork = unitOfWork;
    }

    public ActionResult Index()
    {
        int? id = AccountServices.GetCurrentUserId();
        if (!id.HasValue)
        {
            return RedirectToAction("Login", "Account", new { ReturnUrl = this.HttpContext.Request.Url.AbsolutePath });
        }
        var user = UnitOfWork.UserRepo.Get(id.Value, "Favourites", "Favourites.County", "Favourites.Country");
        //THE ABOVE CALL GETS THE ERROR

        //.....
        return View();
    }

存储库基类

public class RepositoryBase<C, T> : IDisposable
    where C:DbContext, new()
    where T : ModelBase
{
    private DbContext _context;
    public DbContext Context
    {
        get
        {
            if (_context == null)
            {
                _context = new C();
                this.AllowSerialization = true;
            }
            return _context;
        }
        set
        {
            _context = value;
        }
    }

    public virtual T Get(int Id, params string[] includes)
    {
        if (Id > 0)
        {
            var result = Context.Set<T>().Where(t => t.Id == Id);
            foreach (string includePath in includes)
            {
                result = result.Include(includePath);
            }
            return result.FirstOrDefault(); //This is where the error occurs.
        }
        else
        {
            throw new ApplicationException("Id is zero (0).");
        }
    }

    //... (More CRUD methods)

    public void Dispose()
    {
        if (Context != null)
        {
            Context.Dispose(); //Debugger never hits this before the error
        }
    }
}

工作单位

public class UnitOfWork:IUnitOfWork
{
    public UnitOfWork(
        //... DI of all repos
        IUserRepository userRepo
        )
    {
        //... save repos to an local property
        UserRepo = userRepo;

        //create a new instance of the context so that all the repo's have access to the same DbContext
        Context = new Context();

        //assign the new context to all the repo's
        //...
        UserRepo.Context = Context;
    }

    public Context Context { get; set; }

    public IUserRepository UserRepo { get; set; }

    //... (some more repositories)

    public void Dispose()
    {
        Context.Dispose(); //THIS IS NOT HIT AT ALL
    }
}

最后,模型容器有这条线

_Instance.RegisterType<IUnitOfWork, UnitOfWork>(new PerThreadLifetimeManager());

如您所见,索引操作将接收一个新的 UnitOfWork 实例,其中包含一个新的 DbContext 对象。但是在第一次调用这个上下文时,它会抛出上述错误。这种模式适用于我的代码中的其他任何地方。

谢谢

更新

下面的答案是使用 perRequestLifetimeManager。以下是合一的含义:

    public class HttpRequestLifetimeManager : LifetimeManager
    {
        private string _key = Guid.NewGuid().ToString();

        public override object GetValue()
        {
            if (HttpContext.Current != null && HttpContext.Current.Items.Contains(_key))
                return HttpContext.Current.Items[_key];
            else
                return null;
        }

        public override void RemoveValue()
        {
            if (HttpContext.Current != null)
                HttpContext.Current.Items.Remove(_key);
        }

        public override void SetValue(object newValue)
        {
            if (HttpContext.Current != null)
                HttpContext.Current.Items[_key] = newValue;
        }
    }
4

2 回答 2

2

我注意到您正在使用 aPerThreadLifetimeManager来控制工作单元类的创建和处置。PerRequestLifetimeManager如果您的 IoC 容器支持,您可能应该将其更改为类似的内容。

于 2012-09-15T06:31:46.857 回答
0

这是因为您正在处理工作单元,在您请求数据之后,在查询后将数据存储在变量中,然后您也可以释放工作单元实例。

于 2012-09-14T12:57:01.220 回答