# logchan's Blog

### Practical multiple providers in Entity Framework Core

I’ve been developing an ASP.Net Core backend. Naturally, Entity Framework (EF) Core is used as the object-database mapper.

One cool thing about EF is that it supports many database providers: sqlite, postgres, mssql, etc. Therefore, I decided to allow configuration-based provider selection. The site administrator can choose a preferred db provider in configuration:

Unfortunately, this is one of a few things that are, albeit documented, quite poorly described in MSDN. After spending an hour to figure out everything not mentioned in the docs, I came up with my own pattern for this, and this post is to keep a reference for myself. Hopefully, others can also benefit from this.

# The usual scenerio

Usually, you have a DbContext subclass, class MyDb : DbContext. Then, it should have a constructor:

And you call AddDbContext in Startup.ConfigureServices:

If you don’t use EF migrations, you’re done. This will work perfectly fine, as long as you configure the database and create it in Startup.Configure:

However, for migrations to work, you need more than what the documentation says.

# Subclassing DbContext

The documentation says that you should subclass MyDb, and override its OnConfiguring method to use the desired provider. If you do follow it, your code won’t compile: you’ll need an additional default constructor for your MyDb class.

Another missing part in the document is that you’ll need to use your subclasses in service configuration. Therefore, they need constructors expecting DbContextOptions<T>, an appropriate constructor should be added to MyDb as well.

Finally, for the similar reason, your OnConfiguring method must exist conditionally. In particular, it must be there only when the binary is built for EF designer tool. Otherwise, it overwrites any configuration you have in normal builds. Therefore, you have to put the OnConfiguring method in an #if block, and create a project configuration (I called mine DebugEf) that defines the flag DEBUG_EF.

In summary, to support sqlite and npgsql, you need two auxiliary classes:

And the MyDb class need two extra constructors:

# Creating migrations

Simply create a migration for each provider. Notice --configuration.

When adding more migrations in the future, --output-dir isn’t required, but --configuration shall be kept.

In your application, you should continue to use MyDb. However, for EF to determine which migration to use, you have to call services.GetService<T> where T is one of the subclasses (instead of MyDb).
Therefore, in Startup.ConfigureServices, register the subclasses:
Then, in Startup.Configure, do the migrations:
In summary, for each extra provider, add one subclass, a two-line case in ConfigureServices, and a case in Configure.