Merging Incremental Migrations in Entity Framework

Tidying up Migrations folder with ease

The story

Have you ever encountered a challenge that looked something like this? You’re assigned to a task force with the mission of implementing a new, exciting feature in your legacy application. You’re grateful to your fellow developers for transitioning from scripted migrations to the Entity Framework and Code-First approach.

You start to roll out new, incremental features. Naturally, these features bring about minor, progressive changes to your models. Along the way, you encounter bugs, and then more bugs… You diligently rectify them and adjust your model. Consequently, numerous incremental changes are made to your database - after all, testing is a must, right?

Then, after some time, your Migrations folder looks like this...

Now, let’s address the elephant in the room… What do you mean these migrations are fake? Well, you’ve caught me… I cleared my migrations folder some time ago… These are merely the result of some clever copy-pasting and obfuscation. But let’s get back on track… What if I told you that you could consolidate all of these changes into one neat, streamlined migration with just a few Package Manager Console (PMC) commands and a single SQL statement? Sounds appealing? Let’s dive in!

The solution

Here is a step by step solution for you:

  1. First, you need to identify the migrations you wish to consolidate. These are typically incremental, so simply select the oldest one from the set that falls within the date-time span of the new feature development.

  2. Following the date-time pattern, you can prepare your list of migrations.

  3. Next, identify any manual modifications you’ve made to the Up() and Down() methods in specific migrations. If there are none, proceed to the next step.

  4. Take note of or remember the oldest migration and delete it along the rest from your project. If your IDE does not automatically update your *.csproj file, ensure to remove the files from the project manifest.

  5. Now, navigate to the target database and locate the __MigrationHistory table. Remove the relevant migrations from the table by executing the following script:

     DELETE TOP(%numberOfMigrationsToDelete%)
     FROM [YourDatabase].[dbo].[__MigrationHistory]
     WHERE MigrationId LIKE '2024%' --you can use any condition for filtering
    
  6. Next, add a single, consolidated migration:
    PM> Add-Migration MyCompleteFeature

  7. To update the database, you can either comment out the Up() method in the MyCompleteFeature migration or proceed with applying the explicit migration and targeting the one that is immediately before the consolidated one. Then, update the database in the usual manner:

    PM> Update-Database -Target [migration_before_consolidation] or / and then

    PM> Update-Database

Done! Quite easy, right? Remember to run all unit tests and do some smoke testing before committing the changes to the repo.

Closing statement

As with any major change, it’s essential to back up your database and codebase before making any potentially irreversible modifications. If you decide to apply old migrations and then reapply the new one, your data will be lost. So proceed with caution.

If you found this post helpful, please hit the like button and share it with your colleagues. If you have any thoughts or comments, I’d be delighted to read them in the comment section below. Thank you for reading!