I am trying to switch to Simple Injector Dependency Injection framework as I am impressed with its speed.
private static void RegisterServices(Container container)
{
container.RegisterPerWebRequest<IDbContext, DbContext1>();
////container.RegisterPerWebRequest<IDbContext, DbContext2>();
container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
container.RegisterPerWebRequest<IColourRepository, ColourRepository>();
where DbContext1 and DbContext2 inherit from a BaseDbContext class
public class BaseDbContext<TContext> : DbContext, IDbContext where TContext : DbContext
which implements a rather simple IDbContext interface (like the many offered on SO), e.g:
public interface IDbContext
{
IQueryable<TEntity> Find<TEntity>() where TEntity : class;
DbSet<TEntity> Set<TEntity>() where TEntity : class;
int SaveChanges();
void Dispose();
}
If I use just a single DbContext class, it works fine - repositories get injected, data pulled etc.
However, I'd also like to use bounded contexts with a smaller number of DbSets in each of them (Shrink EF Models with DDD Bounded Contexts) as my Code-First DbContext would otherwise include hundreds of classes
private static void RegisterServices(Container container)
{
container.RegisterPerWebRequest<IDbContext, DbContext1>();
container.RegisterPerWebRequest<IDbContext, DbContext2>();
container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
container.RegisterPerWebRequest<IColourRepository, ColourRepository>();
Then I get an exception:
System.InvalidOperationException was unhandled by user code
HResult=-2146233079
Message=Type IDbContext has already been registered and the container is currently not configured to allow overriding registrations. To allow overriding the current registration, please set the Container.Options.AllowOverridingRegistrations to true.
Source=SimpleInjector
StackTrace:
at SimpleInjector.Container.ThrowWhenTypeAlreadyRegistered(Type type)
at SimpleInjector.Container.AddRegistration(Type serviceType, Registration registration)
at SimpleInjector.Container.Register[TService,TImplementation](Lifestyle lifestyle, String serviceTypeParamName, String implementationTypeParamName)
at SimpleInjector.Container.Register[TService,TImplementation](Lifestyle lifestyle)
at SimpleInjector.SimpleInjectorWebExtensions.RegisterPerWebRequest[TService,TImplementation](Container container)
If I follow the suggestion:
container.Options.AllowOverridingRegistrations = true;
then DbContext2 seems to override DbContext1, e.g. DbSet "Colour" is in DbContext1 and it is not accessible any more:
Additional information: The entity type Colour is not part of the model for the current context.
How should I use Simple Injector and bounded DbContexts together?
[UPDATE]
The DbContexts are no used in controllers directly, they are dependencies of repositories which Simple Injector should be able to initialise in constructors
public class ColoursController : ApiController
{
private readonly IColourRepository _repository;
private readonly ModelFactory _modelFactory;
public ColoursController(IColourRepository repository)
{
_repository = repository;
_modelFactory = new ModelFactory();
}
where
public class ColourRepository : Repository<Colour>, IColourRepository
{
public ColourRepository(IDbContext context) : base(context) { }
ColourRepository expects a concrete implementation of DbContext1, but some other repository would need DbContext2 (with a different set of entities)
I do not see the reason why it is impossible to use IDbContext interface (or a base type) for both DbContext1 and DbContext2.
Unity can do it:
container.RegisterType<IDbContext, NorthwindContext>(new PerRequestLifetimeManager(), "NorthwindContext");
container.RegisterType<IDbContext, NorthwindCustomerContext>(new PerRequestLifetimeManager(), "NorthwindCustomerContext");
Ninject can do it.
Simple Injector mentions CompositeLogger - maybe that one could do the trick?
https://simpleinjector.org/