Search code examples
c#entity-frameworksimple-injector

Registering multiple DbContext using Simple Injector


I have two derived DbContext types in my application:

  • MyDbContext which maps to a database that I can control
  • ExternalDbContext which maps to database that I cannot control (this one's new and needs to be added)

In the application I'm also using the Decorator pattern where I have a SaveChangesDecorator class that wraps Business Logic. This decorator is injected a DbContext type and calls the .SaveChanges() method on it.

public class SaveChangesDecorator : IWhatever
{
    private readonly DbContext dbContext;
    private readonly IWhatever decoratee;

    public SaveChangesDecorator(DbContext dbContext, ...)
    {
         this.dbContext = dbContext;
         ...
    }

    public void Whatever()
    {
         this.decoratee.Whatever()
         this.dbContext.SaveChanges();
    }
}

Now it depends on the use case which (or both) derived DbContext gets injected in the Business Logic. I had the following registration:

var databaseContextRegistration = scopedLifestyle.CreateRegistration(
    () => new MyDbContext(connectionString), container);

container.AddRegistration(typeof(MyDbContext), databaseContextRegistration);
container.AddRegistration(typeof(DbContext), databaseContextRegistration);

Now I can't add ExternalDbContext to the registration, because that would be ambiguous. Would the best option be to register DbContext as a collection for this scenario?


Solution

  • Now I can't add ExternalDbContext to the registration, because that would be ambiguous.

    Registering ExternalDbContext as DbContext not only is ambiguous in your registration, it is ambiguous in your application, because depending on DbContext is a Liskov Substitution Principle violation, assuming that ExternalDbContext has a different schema.

    If it has a different schema, classes that use DbContext and expect your 'normal' database would break if you supply them with the ExternalDbContext.

    This typically means that you give each context its own 'interface', which is what you are already doing. My advice therefore is to lose the DbContext registration and just register ExternalDbContext and MyDbContext and inside your decorator inject both instances.