Multiple DbContext's with migrations on a single database
Here is a small problem I ran into while working on my current project. This project already has an Entity Framework DbContext
class with entities and a database. I’m adding a new feature but want to keep the changes as isolated as possible. So I wanted to create a second DbContext
that handles the entities specific to my new feature.
Adding the context to the codebase is no hassle, just create the new class and derive it from DbContext
. The problem is in the migrations. Entity Framework has a system that can track changes to the model and apply those changes to the actual database. To keep track of these changes, Entity Framework uses a table called __MigrationHistory
where it stores all kinds of metadata about the model that it can compare to when you make changes to your entities in code.
If a second DbContext
is added, and I enable migrations on it, it will create a second __MigrationHistory
table. That’s not going to work because that table already exists and contains migration data from the other DbContext
!
To get around this we use a feature of the database itself: Schema’s. If we tell the new DbContext
to work on a different schema
than the rest of the database, it’ll be like it’s working on its own database while still getting easy access to existing tables. So how do we get the DbContext
to work on a different schema? Turns out that’s really easy:
public class TheNewContext : DbContext
{
<snip>
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("TheNewSchema");
}
}
Open the class that represents the new DbContext
and override the OnModelCreating
method. This gives you access to the modelbuilder where you can set a default schema for this specific context. If you now enable migrations on the context and create the database from the new model it will live in its own set of tables grouped by the default schema you gave it.
And that’s all there is to it. You now have a single database that is accessed by two different DbContext
’s each with their own migration history.