在 WebApi 中使用 Unity 解析每个请求的 dbcontext

Resolving dbcontext per request with Unity in WebApi

我正在努力完成这项工作。我已经安装了 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 运行时错误。

任何人都可以 suggestion/example 在 WebApi 中使用 Unity 解析每个请求的 dbcontext,最好没有任何 mvc 依赖?

我注入数据库上下文的方式就是问题所在。 Unity 会记住创建的实例并为创建的所有新 AuditService 实例注入相同的实例。我只需要如下解析数据库上下文。

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

PerThreadLifetimeManager 完成了这项工作,考虑到每个 Web 请求都将由不同的线程处理,应该没问题。

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

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

ConfigureContainer class 只是一个 class,我在其中声明我的 IOC 依赖项,如下所示:

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

        }

使用 HierarchicalLifetimeManager 生命周期管理器非常重要,这样每个请求都会获得一个新实例。

UnityResolver class 看起来像这样:

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

然后我使用 Generic Repistory 获得一个新的数据库上下文,如下所示:

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

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

希望对您有所帮助。

更多信息:http://www.asp.net/web-api/overview/advanced/dependency-injection