2013-11-02 27 views
4

我想切換到簡單噴油器依賴注入框架,因爲我對它的速度印象深刻。帶有幾個有界DbContexts的簡單噴油器 - 異常「IDbContext已經註冊」

private static void RegisterServices(Container container) 
{ 
    container.RegisterPerWebRequest<IDbContext, DbContext1>(); 
    ////container.RegisterPerWebRequest<IDbContext, DbContext2>();  
    container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>(); 
    container.RegisterPerWebRequest<IColourRepository, ColourRepository>(); 

其中DbContext1和DbContext2從BaseDbContext類繼承

public class BaseDbContext<TContext> : DbContext, IDbContext where TContext : DbContext 

它實現了一個相當簡單的IDbContext界面(像SO提供的許多),例如:

public interface IDbContext 
{ 
    IQueryable<TEntity> Find<TEntity>() where TEntity : class; 
    DbSet<TEntity> Set<TEntity>() where TEntity : class; 
    int SaveChanges(); 
    void Dispose(); 
} 

如果我只使用單個DbContext類,它工作正常 - 存儲庫被注入,數據被拉等。

不過,我也希望他們每個人(Shrink EF Models with DDD Bounded Contexts)的使用限界上下文與DbSets的數量較少我的代碼優先的DbContext否則將包括幾百個類

private static void RegisterServices(Container container) 
{ 
    container.RegisterPerWebRequest<IDbContext, DbContext1>(); 
    container.RegisterPerWebRequest<IDbContext, DbContext2>(); 

    container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>(); 
    container.RegisterPerWebRequest<IColourRepository, ColourRepository>(); 

然後我得到一個異常:

System.InvalidOperationException了由用戶代碼 的HResult = -2146233079 消息=類型IDbContext已經被註冊並且容器被當前未配置爲允許重寫註冊未處理。要允許覆蓋當前註冊,請將Container.Options.AllowOverridingRegistrations設置爲true。 源= SimpleInjector 堆棧跟蹤: 在SimpleInjector.Container.ThrowWhenTypeAlreadyRegistered(類型類型) 在SimpleInjector.Container.AddRegistration(類型的serviceType,登記註冊) 在SimpleInjector.Container.Register [TService,TImplementation](生活方式生活方式,字符串serviceTypeParamName ,字符串implementationTypeParamName) 在SimpleInjector.Container.Register [TService,TImplementation](生活方式生活方式) 在SimpleInjector.SimpleInjectorWebExtensions.RegisterPerWebRequest [TService,TImplementation](容器容器)

如果我按照建議:

container.Options.AllowOverridingRegistrations = true; 

然後DbContext2似乎覆蓋了DbContext1,例如, DbSet「顏色」是DbContext1,它是無法訪問任何更多:

Additional information: The entity type Colour is not part of the model for the current context. 

我應該如何用簡單的噴油器和有限DbContexts在一起嗎?

[UPDATE]

的DbContexts都沒有在控制器中使用直接,它們是儲存庫,其簡單的進樣器應該能夠在構造

public class ColoursController : ApiController 
{ 
    private readonly IColourRepository _repository; 
    private readonly ModelFactory _modelFactory; 

    public ColoursController(IColourRepository repository) 
    { 
     _repository = repository; 
     _modelFactory = new ModelFactory(); 
    } 

其中

public class ColourRepository : Repository<Colour>, IColourRepository 
{ 
    public ColourRepository(IDbContext context) : base(context) { } 

初始化的依賴關係ColourRepository需要DbContext1的具體實現,但其他一些存儲庫需要DbContext2(具有不同的實體集合)

我看不到爲什麼不可能爲DbContext1和DbContext2使用IDbContext接口(或基本類型)的原因。

團結可以做到這一點:

container.RegisterType<IDbContext, NorthwindContext>(new PerRequestLifetimeManager(), "NorthwindContext"); 
container.RegisterType<IDbContext, NorthwindCustomerContext>(new PerRequestLifetimeManager(), "NorthwindCustomerContext"); 

Ninject可以做到這一點。

簡單的噴油器提到CompositeLogger - 也許這可以做到這一點?

https://simpleinjector.org/

+0

你期望什麼行爲?當你爲同一類型進行兩次註冊時,應該注入哪一個註冊?簡單的注射器可以防止您進行模糊的註冊並因此引發。你想達到什麼目的?哪種情況必須在什麼情況下注入? – Steven

+0

我想以某種方式註冊DbContext1和DbContext2,因爲它們包含數據集的子集。它們由存儲庫使用,所以當我在構造器中注入存儲庫時:public ColoursController(IColourRepository存儲庫)我期望它能夠使用DbContext1。公共類ColourRepository:版本庫,IColourRepository {public ColourRepository(IDbContext上下文):base(上下文){} – AFD

+0

@ADNow你試過這個嗎?var webLifestyle = new WebRequestLifestyle(); container.Register (webLifestyle); container.Register (webLifestyle); – Spock

回答

5

ColourRepository需要一個具體的實施DbContext1,但 一些其他的庫需要DbContext2(一組不同的 實體)

你的設計是目前含糊不清。雖然你的設計講述了一個IDbContext,看起來好像是兩個實現只有一個抽象,但這些實現不可互換(違反Liskov Substitution principle),這表明事實上應該有兩個不同的接口。此外,只有一個界面使您的DI配置更加複雜和難以維護(這與您選擇的框架無關)。

因此,解決方案是通過爲每個上下文提供自己的接口來消除設計中的歧義。這使您的存儲庫來承擔他們所需要的抽象的依賴:

public class ColourRepository : Repository<Colour>, IColourRepository 
{ 
    public ColourRepository(ICustomerDbContext context) : base(context) { } 
} 

而且這可以讓你簡化登記:

container.Register<IDbContext, NorthwindContext>(Lifestyle.Scoped); 
container.Register<ICustomerDbContext, NorthwindCustomerContext>(Lifestyle.Scoped); 

注意,使用密鑰的註冊將不會解決的核心問題;你仍然會被迫明確指出哪個密鑰版本應該被注入到哪個版本庫中,這會使你的DI配置成爲一個維護噩夢,並且非常容易出錯。

+0

嗨史蒂文,我知道你是這方面的大師,避免你最終提到的核心問題的推薦方法是什麼? – AFD

+0

@ADNow:正如我在我的回答中提到的,解決方案是重構遠離歧義。這可以像添加從(IDbContext)繼承的(空)'ICustomerDbContext'接口一樣簡單。 – Steven

+0

好的,謝謝。不建議公開ColourRepository(ICustomerDbContext上下文) – AFD

相關問題