Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving dbcontext per request with Unity in WebApi

I am struggling to make this work. I've got Unity and Unity.AspNet.WebApi packages (v 3.5.1404) installed and below activation code which came with the packages

public static class UnityWebApiActivator
{
    /// <summary>Integrates Unity when the application starts.</summary>
    public static void Start() 
    {
        var container = UnityConfig.GetConfiguredContainer();
        var resolver = new UnityHierarchicalDependencyResolver(container);

        GlobalConfiguration.Configuration.DependencyResolver = resolver;

        // DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
    }

    /// <summary>Disposes the Unity container when the application is shut down.</summary>
    public static void Shutdown()
    {
        var container = UnityConfig.GetConfiguredContainer();
        container.Dispose();
    }
}

and my type registration looks like this:

 public static void RegisterTypes(IUnityContainer container)
        {
            container.RegisterType<IAuditService, AuditService>(
                new PerThreadLifetimeManager(),
                new InjectionConstructor(new SecurityDbContext()));
        }

So far I've tried PerThreadLifetimeManager and TransientLifetimeManager with no success. I've also got the Unity.Mvc package and tried using the PerRequestLifetimeManager as suggested by msdn but no luck. It always gives me the same instance of dbcontex.

I rather do not include any MVC dependency as this is purely WebApi but when I try to use Unity.Mvc, I ended up some http runtime errors too.

Anyone has a good suggestion/example to resolve dbcontext per request with Unity in WebApi, preferably without any mvc dependency?

like image 290
Otake Avatar asked Feb 11 '15 12:02

Otake


Video Answer


2 Answers

The way I was injecting db context was the problem here. Unity remembers the instance created and injects the same instance for all new AuditService instance created. I simply needed to resolve the db context as below.

container.RegisterType<DbContext, SecurityDbContext>(new PerThreadLifetimeManager());

PerThreadLifetimeManager did the work and it should be fine considering each web requests will be served by a different thread.

like image 76
Otake Avatar answered Sep 19 '22 09:09

Otake


I managed to resolve per request by declaring my custom UnityResolver's class within the WebApiConfig class. The UnityResolver class uses the HttpConfiguration class assuming you're using an OWIN context.

public static void Register(HttpConfiguration config)
        {    
            // Web API configuration and services
            var _container = new UnityContainer();
            DependencyConfiguration.ConfigureContainer(_container);
            config.DependencyResolver = new UnityResolver(_container);
         }

The ConfigureContainer class is simply a class where I declare my IOC dependencies as shown below:

private static void RegisterReleaseEnv(IUnityContainer container)
        {
            //Repository Registration
            container             
              .RegisterType(typeof(IRepository<>), typeof(GenericRepository<>), new HierarchicalLifetimeManager());

        }

It is very important that you use the HierarchicalLifetimeManager lifetime manager so that you get a new instance per request.

The UnityResolver class then looks like this:

public class UnityResolver : IDependencyResolver
    {
        protected IUnityContainer container;

        public UnityResolver(IUnityContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }
            this.container = container;
        }

        public object GetService(Type serviceType)
        {
            try
            {
                return container.Resolve(serviceType);
            }
            catch (ResolutionFailedException)
            {
                return null;
            }
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            try
            {
                return container.ResolveAll(serviceType);
            }
            catch (ResolutionFailedException)
            {
                return new List<object>();
            }
        }

        public IDependencyScope BeginScope()
        {
            var child = container.CreateChildContainer();
            return new UnityResolver(child);
        }

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

I then get a new DB Context using a Generic Repistory as shown below:

public class GenericRepository<TEntity> : IRepository<TEntity>, IDisposable where TEntity : class
{
    internal BackendContainer context;
    internal DbSet<TEntity> dbSet;

    public GenericRepository(BackendContainer context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }

    public GenericRepository()
        : this(new BackendContainer())
    {
    }


    public virtual IQueryable<TEntity> All()
    {
        return dbSet.AsQueryable();
    }
}

Because of the Unity Resolver, the Generic Repository is instantiated per request and so is the DbContext (BackendContainer).

I hope this helps.

For more information: http://www.asp.net/web-api/overview/advanced/dependency-injection

like image 39
Shaun Grech Avatar answered Sep 22 '22 09:09

Shaun Grech