2013-11-02 26 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

相关问题