2015-02-11 17 views
11

Tôi đang nỗ lực để thực hiện công việc này. Tôi đã có Unity và các gói Unity.AspNet.WebApi (v 1404/05/03) được cài đặt và mã kích hoạt bên dưới mà đi kèm với các góiGiải quyết dbcontext theo yêu cầu với Unity trong WebApi

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

và đăng ký loại của tôi trông như thế này:

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

Cho đến nay tôi đã thử PerThreadLifetimeManager và TransientLifetimeManager không thành công. Tôi cũng đã có gói Unity.Mvc và đã thử sử dụng PerRequestLifetimeManager theo gợi ý của msdn nhưng không may mắn. Nó luôn mang lại cho tôi cùng một thể hiện của dbcontex.

Tôi không bao gồm bất kỳ phụ thuộc MVC nào vì đây hoàn toàn là WebApi nhưng khi tôi cố gắng sử dụng Unity.Mvc, tôi đã kết thúc một số lỗi thời gian chạy http.

Bất kỳ ai có đề xuất/ví dụ tốt để giải quyết dbcontext theo yêu cầu với Unity trong WebApi, tốt nhất là không có bất kỳ phụ thuộc mvc nào?

Trả lời

12

Cách tôi đã tiêm bối cảnh db là vấn đề ở đây. Unity nhớ cá thể đã tạo và tiêm cùng một cá thể cho tất cả cá thể AuditService mới được tạo ra. Tôi chỉ cần giải quyết bối cảnh db như dưới đây.

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

PerThreadLifetimeQuản lý đã thực hiện công việc và cần cân nhắc mỗi yêu cầu web sẽ được phân phát theo một chuỗi khác nhau.

+0

Không thể nhận được 'SecurityDbContext' này. Đây có phải là tự định nghĩa một lớp mà kế thừa lớp Dbcontext không? – picnic4u

+0

Có SecurityDbContext kế thừa DbContext và đó là nơi tôi thêm ánh xạ EF bằng cách ghi đè phương thức OnModelCreating. – Otake

+0

@Otake như thế nào nó tuyên bố trên Controller để nó hoạt động? Tks – Pascal

1

Tôi đã quản lý để giải quyết theo yêu cầu bằng cách khai báo lớp của UnityResolver tùy chỉnh của tôi trong lớp WebApiConfig. Lớp UnityResolver sử dụng lớp HttpConfiguration giả sử bạn đang sử dụng một ngữ cảnh OWIN.

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

Lớp ConfigureContainer chỉ đơn giản là một lớp học nơi tôi tuyên bố phụ thuộc IOC tôi như hình dưới đây:

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

     } 

Điều rất quan trọng mà bạn sử dụng người quản lý HierarchicalLifetimeManager đời để bạn có được một trường hợp mới mỗi yêu cầu.

Lớp UnityResolver sau đó trông như thế này:

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

sau đó tôi nhận được một bối cảnh DB mới sử dụng Generic Repistory như hình dưới đây:

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

Do Unity Resolver, Generic Repository được khởi tạo theo yêu cầu và do đó là DbContext (BackendContainer).

Tôi hy vọng điều này sẽ hữu ích.

Để biết thêm thông tin: http://www.asp.net/web-api/overview/advanced/dependency-injection

Các vấn đề liên quan