Update-Database fails due to Pending Changes, but Add-Migration Creates a Duplicate Migration

This answer explains why it happens. To resolve it I call add-migration and name it MERGE and then remove any duplicate migration code that has already happened. This is just to update the model snapshot to reflect the merged model.

Example:

public partial class MERGE : DbMigration
{
    public override void Up()
    {
        // Intentionally left blank.

        // This may seem like a hack, but it is necessary when using source control.
        // When a migration is created via add-migration, EF creates 
        // an .edmx file from the current code first classes. It compares this .edmx to the .edmx stored in the last migration before this, 
        // which I'll call it's parent migration. The edmx snapshots are gzipped and stored in base64 in the resource files (.resx) if you 
        // want to see them. EF uses the difference between these two snapshots to determine what needs to be migrated.

        // When using source control it will happen that two users add entities to the model independently. The generated edmx snapshots will 
        // only have the changes that they have made. When they merge in source control, they will end up with this:

        // Migration                        |  Snapshot Contents
        // -------------------------------- | ----------------
        // 20150101_Parent Migration        |  A
        // 20150102_Developer 1's Migration |  A + Change 1
        // 20150103_Developer 2's Migration |  A + Change 2

        // So calling add-migration will create the current snapshot edmx from the Code First model and compare it to the 
        // the latest migration's snapshot, which is A + Change 2, and see that Change 1 is missing. That is why it 
        // creates a duplicate migration. We know that the migrations have already been applied, so the only thing that this 
        // migration will do is update the current snapshot .edmx so that later migrations work fine.
    }

    public override void Down()
    {

    }
}

I see this all the time also. I don't know why, wish i did, but my solution is to do a add-migration which will make a duplicate. Now this duplicate opens in the editor and then i edit it, so that the Up and Down methods are empty. So the result is a migration file that does nothing! VS is happy and you can do the update-database without errors (until next time).

I hope this helps :)


As a general answer to this part of the question:

(I am working alone, but am simulating team work on branches to learn more about git too), and trying to get the database in step with the merge. Might this have come about from placing migrations in some particular order after a merge

Yes, that may well be the case, it's fairly easy for EF to get confused after a merge, but it is possible to resolve it. The key is understanding why it got confused in the first place:

What happens when migrations are merged from branches?

The reason EF gets confused is that EF stores the current shape of the database in the actual migration file, it's the 'Target' value in the resx file found under each migration, e.g.

migration file in solution explorer showing child .resx file

migration resx file showing the Target

Imagine you have two branches:

  • Branch 1: You add 'URL' field to the Blog table. The Target field now has a description of the database with that extra field
  • Branch 2: You add a new 'Links' table. Again, the db description in the Target field now has that extra table, but it doesn't have the URL field as that was added on a different branch

If you now merge both of those branches back onto the master branch and then try to run migrations you may well get the dreaded

Unable to update database to match the current model because there are pending changes and automatic migration is disabled...

That error message is really unhelpfully misleading, but the cause of the error is actually fairly simple to understand:

Why do multiple branches confuse EF?

When the two branches were merged back onto Master, whichever of them is now the last migration (as per the dates at the starts of the filename) is considered by EF to have the true current state of the database in that migration's Target field.

However, as we saw above, Branch 1 and Branch 2 both have different views of what the true state of the database is (one thinks there's a new URL field, the other thinks there's a new links field), and unhelpfully they are now both wrong because the database has both of those fields now.

The error message occurs because EF computes the expected state of the DB from the actual steps in the migrations and compares that to the Target and finds they are different.

How to fix it

The solution to all of this is to force EF to recompute the state of the database based on all the migrations now in the project and then update the Target value to one that includes the changes made on all the migrations.

The simplest way to do that is simply to add a 'blank' migration, using the command:

Add-Migration <pick_a_name> –IgnoreChanges

The alternative approach is to overwrite the Target value in the final migration.

Consult the manual..

All of the above is a brief overview of the superb guide to understanding migrations in general and also in a team environment that can be found in:

Microsoft's Code First Migrations in Team Environments

That document should be referred to in every EF error message as it makes sense of so many day to day EF issues.