Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF 4.3 Auto-Migrations with multiple DbContexts in one database

I'm trying to use EF 4.3 migrations with multiple code-first DbContexts. My application is separated into several plugins, which possibly have their own DbContext regarding their domain. The application should use one single sql-database.

When I try to auto migrate the contexts in an empty database, this is only successful for the first context. Every other context needs the AutomaticMigrationDataLossAllowed-Property set to true but then tries to drop the tables of the previous one.

So my question is:

  • How can I tell the migration-configuration just to look after the tables defined in their corresponding context and leave all others alone?
  • What is the right workflow to deal with multiple DbContexts with auto-migration in a single database?

Thank you!

like image 707
Joachim Rosskopf Avatar asked Feb 02 '12 10:02

Joachim Rosskopf


3 Answers

Here is what you can do. very simple.

You can create Configration Class for each of your context. e.g

internal sealed class Configuration1 : DbMigrationsConfiguration<Context1>{    public Configuration1 (){         AutomaticMigrationsEnabled = false;         MigrationsNamespace = "YourProject.Models.ContextNamespace1";    } }  internal sealed class Configuration2 : DbMigrationsConfiguration<Context2>{    public Configuration2 (){         AutomaticMigrationsEnabled = false;         MigrationsNamespace = "YourProject.Models.ContextNamespace2";    } } 

Now you add migration. You dont need to enable migration since you already did with the 2 classed above.

Add-Migration -configuration Configuration1 Context1Init 

This will create migration script for context1. your can repeat this again for other Contexts.

Add-Migration -configuration Configuration2 Context2Init 

To Update your database

Update-Database -configuration Configuration1 Update-Database -configuration Configuration2 

This can be done in any order. Except you need to make sure each configration is called in sequence.

like image 131
Anuj Pandey Avatar answered Dec 03 '22 09:12

Anuj Pandey


Code First Migrations assumes that there is only one migrations configuration per database (and one context per configuration).

I can think of two possible solutions:

  1. Create an aggregate context that includes all the entities of each context and reference this "super" context from your migrations configuration class. This way all the tables will be created in the user's database, but data will only be in the ones that they've installed plugins for.

  2. Use separate databases for each context. If you have shared entities between the contexts, add a custom migration and replace the CreateTable(...) call with a Sql("CREATE VIEW ...") call to get the data from the entity's "originating" database.

I would try #1 since it keeps everything in a single database. You could create a seperate project in your solution to contain your migrations and this "super" context. Just add the project, reference all of your plugins' projects, create a context that includes all of the entities, then call Enable-Migrations on this new project. Things should work as expected after that.

like image 34
bricelam Avatar answered Dec 03 '22 09:12

bricelam


I have a working site with multiple contexts using migrations. However, you do need to use a separate database per context, and it's all driven off of a *Configuration class in the Migrations namespace of your project, so for example CompanyDbContext points to Company.sdf using CompanyConfiguration. update-database -configurationtypename CompanyConfiguration. Another LogDbContext points to Log.sdf using LogConfiguration, etc.

Given this works, have you tried creating 2 contexts pointing at the same database and telling the modelbuilder to ignore the other context's list of tables?

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Ignore<OtherContextsClass>();
    // more of these
}

Since the migrations work with the ModelBuilder, this might do the job.

The crappy alternative is to avoid using Automatic Migrations, generate a migration each time and then manually sift through and remove unwanted statements, then run them, although there's nothing stopping you from creating a simple tool that looks at the Contexts and generated statements and does the migration fixups for you.

like image 21
Chris Moschini Avatar answered Dec 03 '22 09:12

Chris Moschini