Entity-framework – How to skip previous ef migrations on a new database that already contains those changes

entity-frameworkentity-framework-4entity-framework-migrations

The scenario I'm having problems with is as follows:

  1. Code First model created using EF 4.1 and corresponding database generated
  2. EF upgraded to 4.3.1 and a migration added (using IgnoreChanges because no model changes) to start using migrations (__MigrtionHistory table created and EdmMetadata dropped) – let's call it 'InitialMigration'
  3. Model is changed, say a new property is added and a migration that adds a corresponding column is generated (let's call this one 'NewPropertyMigration') and then applied to a Dev database (using our version of Migrate To Latest initialization strategy)
  4. When code is promoted to production the database there is updated with new column as expected
  5. Then when a brand new database is created in Dev and because it is based on latest model it will include the new column right after it is created but when the initialization strategy is run it still finds 'InitialMigration' and 'NewPropertyMigration' as pending but they both fail because EdmMetadata is not there so nothing to be removed and new column is already there so can't add

When I check __MigrationHistory table on this new database it only contains 'InitialCreate' entry so that would explain why the other two migrations are considered as pending. But I can't see how they would ever get into this table without being applied and at the same time they don't really need to be applied because database already contains any changes they cover.
What am I missing?

I'll just add that it seems a bit suspicious that the Model column in 'InitialCreate' is different to the one in 'NewPropertyMigration' even though they represent the same model. Could that be the cause?

Update:
This is the code I use to create new database and apply any migrations automatically at the same time

public class MigratePaymentsToLatestVersion<TContext> : IDatabaseInitializer<TContext> where TContext : DbContext
{
public void InitializeDatabase(TContext context)
{
    // Create a brand new database if it doesn't exist but still apply any pending migrations
    context.Database.CreateIfNotExists();
    var migrator = new DbMigrator(configuration);
    migrator.Update();
}
}

Update 2: Simpler scenario showing the same problem

While investigating this further I've been able to reproduce the behaviour in a much simpler scenario described below:

  1. Create simple model and context
  2. In a test application add one entity – with all default settings database is automatically created and object added
  3. Enable migrations – 'InitialCreate' migration is generated
  4. Update-Database – command returns no pending migrations because 'InitialCreation' is already in __MigrationHistory
  5. Delete database and re-run test application – database is re-created automatically again
  6. At this point I can't add any additional migrations or run update-database because 'InitialCreation' migration is seen as pending but cannot be applied because all entities already exist

Best Answer

I have it sorted now. The crucial bit I was missing seems to be related to the way you move from 4.1 to 4.3. I have been following steps from ef-4-3-migrations-and-existing-database. What seems to work better is the procedure described in the SO question how-to-use-migrations-on-an-existing-db. If you compare both of them you'll see that one relies on -IgnoreChanges when you do first migration (called 'InitialMigration') while the other one creates a full 'InitialCreate' migration that contains your entire model at that point in time. Two important consequences of the latter approach are: - when creating a brand new database InitialCreate migration, which contains full definition of the model, is used to create database instead of 'the other code' (not sure exactly but guessing that this is the part that is needed when migrations are not enabled) that generates database based on the model - new database is created with up-to-date model and with all migrations listed in __MigrationHistory

So with the InitialCreate approach I am able to apply migrations to existing databases (for them the InitialCreate is simply skipped because an entry in history is added manually as part of the procedure) and at the same time I am able to create brand new databases and add new migrations to them without getting an error that model and db are out-of-sync.

I hope that helps people who, like me, followed the first procedure.