在Web Api中使用Unity解决每个请求的dbcontext

时间:2015-02-11 12:11:38

标签: c# entity-framework asp.net-web-api dependency-injection

我正在努力做这项工作。我已经安装了Unity和Unity.AspNet.WebApi软件包(v 3.5.1404)以及随软件包附带的激活码

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();
    }
}

我的类型注册如下:

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

到目前为止,我已经尝试过PerThreadLifetimeManager和TransientLifetimeManager但没有成功。我也得到了Unity.Mvc包并尝试使用msdn建议的PerRequestLifetimeManager,但没有运气。它总是给我相同的dbcontex实例。

我宁愿不包含任何MVC依赖,因为这纯粹是WebApi,但是当我尝试使用Unity.Mvc时,我也结束了一些http运行时错误。

任何人都有一个很好的建议/示例,在WebApi中使用Unity解析每个请求的dbcontext,最好没有任何mvc依赖?

2 个答案:

答案 0 :(得分:14)

我注入db上下文的方式就是这里的问题。 Unity会记住创建的实例,并为创建的所有新AuditService实例注入相同的实例。我只需要解决db上下文,如下所示。

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

PerThreadLifetimeManager完成了工作,考虑到每个Web请求将由不同的线程提供服务,应该没问题。

答案 1 :(得分:2)

我设法通过在WebApiConfig类中声明我的自定义UnityResolver类来解决每个请求。 UnityResolver类使用HttpConfiguration类,假设您正在使用OWIN上下文。

512 bytes

ConfigureContainer类只是一个我声明IOC依赖关系的类,如下所示:

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

使用HierarchicalLifetimeManager生命周期管理器非常重要,这样您就可以获得每个请求的新实例。

UnityResolver类看起来像这样:

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

        }

然后我使用Generic Repistory获取一个新的DB Context,如下所示:

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();
        }
    }

由于Unity解析器,通用存储库是根据请求实例化的,因此是DbContext(BackendContainer)。

我希望这会有所帮助。

有关详细信息:http://www.asp.net/web-api/overview/advanced/dependency-injection