Merging migration entries in Entity Framework - c#

I have an Entity Framework 6 CF project that has a few migrations already in place.
The model is now stable and there is no need to keep the migration history that already exists.
Is there a way to reset the model and merge all migration commands into the initial migration?
As an example, the first migration adds a column while the second migration adds a unique, non-clustered index. I now want to see all these changes directly in OnModelCreating rather than in separate migrations.

Migrations have both an Up and Down. You can always Re-Scaffold your application by tearing the migrations down and then adding a new migration. The Down process does not change your model, only the changes to the database. Use Update-Database -Target:migrationTargetName or Update-Database -TargetMigration:migrationNumber.
If you want a migration which starts with no database and ends with your current model, you can tear all the migrations down with Update-Database -TargetMigration:0. It's a good idea to tear down the database and then run Update-Database as a test to verify the database changes are all in sync.
Bear in mind, if you tear your migrations down to 0 and then run an Add-Migration, you will want to look very closely at the generated scaffold, as it will likely be drastically different than the incremental changes.

Related

Adding EF Core Migrations to an existing database, while still enabling creation of the database from scratch

Last year, I rewrote a legacy application with .Net Core and EF Core, but elected not to add migrations at the time due to other limiting factors. The time has finally come where the new application can operate as the "single source of truth" for schema changes, but I'm at a bit of a loss as to the best way to move forward.
My end-goal is to have migrations that can scaffold out the entire existing database from nothing (minus the data contained within the non-lookup tables). Unfortunately, the most viable solution I've come up with so far is to build my migrations against a new, blank database. Then once the initial migration is created that matches the state of the current database, I would be able to copy over the __EFMigrationsHistory from the newly created database to the old one.
Alternatively, I can scaffold out a blank initial migration, and I could attempt to add logic in that migration to create the database from a SQL file if it did not exist.
Neither solution seems particularly "good". Aside from tools like FluentMigrator, are there any EF Core-centric approaches that can simplify creating migrations for an existing database that will need to be recreated for tests?
I had a similar issue when I wanted to squash all the existing migrations of the past 5 years (because it took forever to create a new instance). Here's how I did it:
Remove all migrations from your code, including any DbContextModelSnapshot.cs
Scaffold an initial migration: it will contain everything to create a new DB instance
Scaffold another migration, dedicated to seed the initial data (that's optional if you don't need to seed data on your newly created instance). The goal is to isolate the seed from the SQL structure.
Commit your changes
Keep the migrations, but remove the bodies of the Up and Down methods; the goal is to trick EF Core into thinking it applied those migrations
Update your existing instances with those empty migrations: nothing will be done, but the __EFMigrationsHistory table will contain them and ignore them in the future
Revert your changes, to restore the bodies of the migrations
With all those steps, you can now update your existing instances with any future migrations, yet also recreate new instances from scratch.

EF Code First with existing database on another database

The title is a bit confusing but I'm trying to specify that the problem is not initiating a code first model and migration for an existing database, but comes after that.
I needed to activate automatic migration because we switched to a code first model for our system. So, here's what has been done:
I created an empty InitialCreate for the existing database
I did some other scripts because there were some changes, those worked OK and the scripts were created and run on database
The problem happen when I want to use those script and migrate another database that was not yet initialized this way. I don't know what to do.
When I try to run Update-database I get the error:
Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration.
You can use the Add-Migration command to write the pending model changes to a code-based migration.
If I do a Add-Migration it creates a migration with everything in it again, all the create tables, it's like it ignores my currents scripts, the fact that there is a InitialCreate empty and the other scripts.
OK, you have 2 databases - let's say DEV and PROD. Both are in an identical state and have the same schema before migrations have been enabled. This is what to do:
1 - Add migrations to your DEV environment and set your database initializer to MigrateDatabaseToLatestVersion. Another option is to programatically run migrations.
enable-migrations
// take a snapshot of current state. -IgnoreChanges prevents recreate of existing objects.
add-migration InitialBaseline -IgnoreChanges
update-database
2 - There are several ways to keep the other database(s) in sync:
A) Maintain migrations in parallel by changing the connection string. So point at PROD, and run update-database to create the __MigrationHistory table and apply the initial, blank, baseline. I don't recommend this option for PROD databases (see below).
B) Sync with scripts. Many organizations don't want EF applying changes and instead require DBAs to apply scripts. For this option, you may want to set your database initializer to NULL. In this case you can do an update-database -Script to generate changes. This would be done on migrations subsequent to your initial baseline since they are already in sync. See here for more info on this technique.
C) Use database projects or a diff tool to keep things in sync.
Now when you go and change your models in DEV:
add-migration Changes1
update-database
For option A, change connect string and repeat. For option B, use update-database -Script. For option C, resync with tool.
NOTE: "I needed to activate automatic migrations..." - Automatic migrations are a whole different matter and can complicate the process. See here.

Generating MigrationHistory table in reverse engineered code first

I have reverse engineered on existing database for code first. Next i Enabled-Migrating for the context (Code based migration). When i create an initial add-migration it works fine and would apply on an empty database.
But my requirement is that i need to use the same database i used for creating the models because of the data it has.
Now the conundrum is how do i implement the code based migrations. My database does not have a migration history table. So, when i run Update-database, it tries to create the existing tables and fails.
How can i capture the current state in the migration history or instruct EF to create the migration history with the current schema as the starting point.
Do i need to turn on the automatic migration for initial setup. Please suggest.
Note: I am using EF 6.
You need to establish a baseline migration of the existing items. So the first migration you create should be:
add-migration Initial -IgnoreChanges
The ignore changes tells EF to just save a snapshot of the current database. Now any subsequent migrations will not include the existing tables (just the changes). This would allow you to continue updating your existing database since EF will see the record in __MigrationHistory or deploy to a new, empty database.
See the under the hood section here.

Entity Framework migrations changes detection

I've been recently digging into how EF migrations work and I've encountered an issue I could not really understand.
I was reading this article and here's what I saw:
At this stage Developer #2 can run Update-Database which will detect
the new AddRating migration (which hasn’t been applied to Developer
2’s database) and apply it. Now the Rating column is added to the Blogs table and the database is in sync with the model.
What I can't get is how EF determines that it has to apply the changes from the AddRatings migration. As far as I know, the workflow is as follows:
Suppose we have two migrations (with the ids 4 and 5) in the project which have not been applied to the db (say, we got the old version of the db with 1, 2 and 3 migrations applied).
Update Db command is run.
EF goes to the db, looks up the MigrationHistory table and gets the latest migration. Then, EF sees that there are migrations 4 and 5 in the project and since the latest migration in the db is 3, it applies 4 and 5.
However, when I look at the screen from the article, I don't really get it. Here's how I would expect it to go:
There are migrations First, AddUrl and AddReaders in the Dev 2 database.
EF looks up the latest migration in the db - it's the AddReaders.
The latest migration in the project is also AddReaders.
Therefore, no changes have to be applied at all.
There's an issue that the code model and the latest migration model are not the same, but EF is able to apply changes to the db anyway, though producing a warning, as the article says.
The question is, what have I got wrong in my reasoning and how EF understands that even though the latest migration in the db and code is the same, there's another migration that has to be applied.
Also, as far as I've understood, the compressed model in the MigrationHistory serves only when the Add-Migration command is run and has nothing to do with the Update-Database command. Is it so?
When performing an update EF compares the set of migrations from the assembly with the set of migrations from the database and applies to the DB all missing migrations. It doesn't matter whether the missing migrations are at the end of history list or somewhere in the middle.
Migrations are compared by MigrationId so you are right, the compressed model has nothing to do with the Update_Database command.

Database First - trying to recreate my entities that exist

I'm trying to connect my app to an existing Application.
So i created the Entities with the Entity Framework Database First.
It create all my entities and my Context that's fine.
But when i try to run it tell me that my migrations are not up-to-date so i tried to add-migration test to see what was missing...
It's creating all the table i asked it from DataBase First...
I cant recreate those tables i just want to be able to connect to those tables...
I absolutly need to connect to those tables, i cannot create a new one and i cannot clone the database.
How can i achieve this... i didnt find any resources on the subject that goes from the start to the end of the process.
Some help would be awesome!
The Problem: You can't reset migrations with existing tables in the database as EF wants to create the tables from scratch.
What to do:
Delete existing migrations from Migrations_History table.
Delete existing migrations from the Migrations Folder.
Run add-migration Reset. This will create a migration in your Migration folder that includes creating the tables (but it will not run it so it will not error out.)
You now need to create the initial row in the MigrationHistory table so EF has a snapshot of the current state. EF will do this if you apply a migration. However, you can't apply the migration that you just made as the tables already exist in your database. So go into the Migration and comment out all the code inside the "Up" method.
Now run update-database. It will apply the Migration (while not actually changing the database) and create a snapshot row in MigrationHistory.
You have now reset your migrations and may continue with normal migrations.

Categories

Resources