2015-02-11 14 views
11

Bu işi yapmak için uğraşıyorum. Ben yüklü Birlik ve Unity.AspNet.WebApi paketlerini (v 1404/05/03) var ve paketlerin WebApi'de birlik ile istek başına dbcontext'in çözülmesi

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

ve benim tipim kaydı ile aktivasyon kodunu aşağıdaki gibi görünür ettik:

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

Şimdiye kadar PerThreadLifetimeManager ve TransientLifetimeManager denemeyi denemedim. Ayrıca Unity.Mvc paketini aldım ve msdn tarafından önerilen ancak hiç şansın olmadığı şekilde PerRequestLifetimeManager'ı kullanmayı denedim. Her zaman bana aynı dbcontex örneğini verir.

Bu, tamamen WebApi olduğu için MVC bağımlılığı eklememeyi tercih ediyorum ancak Unity.Mvc kullanmayı denediğimde, bazı http çalışma zamanı hataları da sonlandırdım.

Herkes, herhangi bir mvc bağımlılığı olmaksızın WebApi'deki birlik ile istek başına dbcontext çözümlemek için iyi bir öneri/örnek var mı?

cevap

12

db içeriğini enjekte ettiğim yol burada sorun oldu. Unity, oluşturulan örneği hatırlar ve oluşturulan tüm yeni AuditService örneği için aynı örneği enjekte eder. Aşağıdaki gibi db içeriğini çözmek için ihtiyacım vardı.

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

PerThreadLifetimeManager çalışma yaptı ve farklı bir iş parçacığı tarafından servis edilecektir her web isteklerini dikkate ince olmalıdır.

+0

değil bu 'SecurityDbContext' elde edebilmek. Bu, Dbcontext sınıfını miras alan bir sınıf olarak tanımlanmış bir sınıf mı? – picnic4u

+0

Evet SecurityDbContext, DbContext'i miras alır ve OnModelCreating yöntemini geçersiz kılarak EF eşlemelerini eklediğim yerdir. – Otake

+0

@Operatörün nasıl çalıştığını kontrol etsin nasıl? Tks – Pascal

1

Özel UnityResolver sınıfımı WebApiConfig sınıfında bildirerek istek başına gidermeyi başardım. UnityResolver sınıfı, bir OWIN bağlamı kullandığınızı varsayarak HttpConfiguration sınıfını kullanır.

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

     } 

Size yeni bir örneğini başına olsun, böylece her HierarchicalLifetimeManager ömür boyu yöneticisi kullanmanız son derece önemlidir:

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

ConfigureContainer sınıf sadece aşağıda gösterildiği gibi benim IOC bağımlılıkları beyan bir sınıftır istek.

UnityResolver sınıfı sonra şuna benzer:

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

aşağıda gösterildiği gibi Sonra bir Genel Repistory kullanarak yeni DB Bağlam olsun: Çünkü Birlik Resolver, Jenerik Veri Havuzunun

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

istek başına oluşturulur ve DbContext (BackendContainer).

Umarım bu yardımcı olur. Daha fazla bilgi için

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

İlgili konular