DbContext Unity does not call HttpContextLifetimeM

2019-07-20 15:58发布

问题:

I'm defining my DbConntextObj

_container.RegisterType<IDbConntextObj, DbConntextObj>(new HttpContextLifetimeManager<DbConntextObj>());

Unity is not calling the RemoveValue() on the lifetimemanager

I have one Dbcontext for multiple repositories.

My lifetimemanager looks like this:

public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable
    {
        private readonly string _itemName = typeof(T).AssemblyQualifiedName;

        public override object GetValue()
        {
            return HttpContext.Current.Items[_itemName];
        }
        public override void RemoveValue()
        {
            var disposable = GetValue() as IDisposable;
            HttpContext.Current.Items.Remove(_itemName);

            if (disposable != null)
                disposable.Dispose();
        }

        public override void SetValue(object newValue)
        {
            HttpContext.Current.Items[_itemName] = newValue;
        }
        public void Dispose()
        {
            RemoveValue();
        }
    }

Is it a bad thing that DbContext Dispose is not being called? Is there a workaround For Unity and MVC3?

回答1:

Try this.

    public class MvcApplication : HttpApplication
{
    private IUnityContainer unityContainer;
    private HttpContextDisposableLifetimeManager ContextLifeTimeManager;
    /// <summary>
    /// The start method of the application.
    /// </summary>
    protected void Application_Start()
    {
        unityContainer = new UnityContainer();
        ContextLifeTimeManager = new HttpContextDisposableLifetimeManager();
        //for some reason this event handler registration doesn't work, meaning we have to add code to
        //Application_EndRequest as below...
        //this.EndRequest += new EventHandler(ContextLifeTimeManager.DisposingHandler);
        unityContainer.RegisterType<IUnitOfWork, EFUnitOfWork>(ContextLifeTimeManager);
        unityContainer.RegisterType<IRepository<ShoppingCart>, ShoppingCartRepository>(new ContainerControlledLifetimeManager());
    }
    //this seems hackish, but it works, so whatever...
    protected void Application_EndRequest(Object sender, EventArgs e)
    {
        if (ContextLifeTimeManager != null)
        {
            ContextLifeTimeManager.RemoveValue();
        }
    }
}

Then in your LifeTimeManager implementation.

public class HttpContextDisposableLifetimeManager : LifetimeManager, IDisposable
{        
    const string _itemName = typeof(T).AssemblyQualifiedName;

    public void DisposingHandler(object source, EventArgs e)
    {
        RemoveValue();
    }

    public override object GetValue()
    {
        return HttpContext.Current.Items[_itemName];
    }
    public override void RemoveValue()
    {
        Dispose();
        HttpContext.Current.Items.Remove(_itemName);
    }

    public override void SetValue(object newValue)
    {
        HttpContext.Current.Items[_itemName] = newValue;
    }
    public void Dispose()
    {
        var obj = (IDisposable)GetValue();
        obj.Dispose();
    }
}