Merging Incremental Migrations in Entity Framework
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:
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.
Following the date-time pattern, you can prepare your list of migrations.
Next, identify any manual modifications you’ve made to the
Up()
andDown()
methods in specific migrations. If there are none, proceed to the next step.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.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
Next, add a single, consolidated migration:
PM> Add-Migration MyCompleteFeature
To update the database, you can either comment out the
Up()
method in theMyCompleteFeature
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 thenPM> 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!
Subscribe to my newsletter
Read articles from Konrad Przepiórzyński directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Konrad Przepiórzyński
Konrad Przepiórzyński
A dedicated .NET backend developer, currently self-employed and providing my expertise to Eviden Poland in beautiful city of Wroclaw. My development environment of choice is Rider, which I use to create robust and efficient solutions. I have had interest in cloud solutions for some time and currently I'm exploring them as a hobby. I have a passion for self-improvement, always seeking to learn and grow both personally and professionally. Outside of work, I have a keen interest in psychology and theology, finding joy and knowledge in both. As a people person, I thrive in team environments and possess strong leadership skills. My guiding motto is “To lead is to serve and help others improve”, reflecting my commitment to fostering growth and development in those around me. When I'm not around people I commit myself to reading, prayer, Bible study or chilling behind the wheel of my car.