When using Entity Framework Migrations, probably, we are going to have too many migrations, even before we have an initial release of what we are building (I'm not using Automatic Migrations). In one of my previous posts I mentioned this problem around Migrations.Let me show you an example of what I'm talking about.
This is the current list of migrations generated so far for a project I am involved. It's a product that is currently in Beta, and we already have deployed it in a testing environment, where we and our beta testers are performing tests.
I don't want to go into the details of this table, and particularly, how it's used internally by EF, but assume that it is the table that EF uses to know what migrations need to be applied when exists some changes in model.
We are currently at the point where we need to release and prepare a fresh and clean installation in a new environment, but I don't want to have this myriad of migrations, because, in fact, this is my first release and I don't care about the migrations, and how I got this current model, at least in terms of migrations registration. Of course that I do care about knowing how we got the current model version, and for that we have everything registered in source control.
What I really want is:
1 - Exclude all migrations
This is a no brain step. Exclude all the migrations from the VS project. You just need to have some caution if you have some custom code in migrations, such as for example custom indexes creation. In this case, you need to identify these extra actions which will be used again later.
2 - Generate an Initial Create Migration with all the model definition
Now that we have no migrations in our VS project, we can generate a new migration with all the model definition. First, we need to create an empty database and change the connectionstring in the web.config to use this new empty database.
Then, in Package Manager Console, we generate a new migration called InitialCreate
We should check that the migration generated has all the model definition. You can add to it extra indexes that eventually you had add previously.
3 - Just one entry in the __MigrationHistory
Let's try to update the database running the Update-Database in PM, against the empty database
Then check the __MigrationHistory table
It's ok. Just One entry in __MigrationHistory as we wish.
4 - Do not compromise an upgrade to the current test environment
Now, the interesting part. What happens if you try to update the database against the database that we are using so far, in which all migrations are registered in? Let's change Web.config to reuse again the correct connection string and try to upgrade database to see what happens
Ok. It seems that there is no pending changes, which is true, since I didn't any change to my model. But I want to be sure that the changes from now on are applied correctly. So, let's do a minor change to check how the upgrade behaves.
Basically we are adding a new column 'NewProperty' to an existing table. Let's create the migration
And check the generated migration
So far so good. Now let's check what is the result to upgrade the database, running the Upgrade-Database command, but now I will use the -Script option to generate the script instead of running the upgrade
And here is the script
Ok! The change is applied and the migration is registered. Well done!
Just one more note: from this point you can't downgrade to any migration that was excluded from the project, since the class is not in assembly anymore.
Let's recap
With this recipe you can reset migrations, allowing to have again an initial create migration which reflect the current model, which will be applied as a single migration in a clean installation, and at the same time, do not compromise upgrades on current deployed databases, where migrations are already registered.