2

直接呼び出されるコントローラー アクションがありますが、次のエラーがスローされます。

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

遅延実行に関する解決策をオンラインで見つけただけですが、ここでは当てはまらないと思います。コンテキストを使用するすべての場所で (この場合).ToList()またはを呼び出すため.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());

ご覧のとおり、インデックス アクションは、新しい DbContext オブジェクトを含む UnitOfWork の新しいインスタンスを受け取ります。しかし、このコンテキストへの最初の呼び出しで、上記のエラーがスローされます。このパターンは、私のコードのどこでも機能します。

ありがとう

アップデート

以下の答えは、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

PerThreadLifetimeManager作業単位クラスの作成と破棄を制御するためにを使用していることに気付きました。PerRequestLifetimeManagerIC コンテナーがそれをサポートしている場合は、おそらく次のように変更する必要があります。

于 2012-09-15T06:31:46.857 に答える
0

これは、作業単位を破棄しているため、データを要求した後、クエリの後にデータを変数に格納してから、作業単位インスタンスを解放することもできます。

于 2012-09-14T12:57:01.220 に答える