First, I've read these questions/answers:
- EF-migration message
- How can I stop Add-Migration checking my database has no pending migrations when using Code-Based migrations?
- Make EF4.3 Code First Migrations ignore pending migrations
These all seem to be for EF versions prior to EF5, and my situation doesn't seem to fit these answers. So, let me describe my situation.
- My application was originally created using EF4, model first. I designed my database with the GUI designer, and used it to generate my database.
- I've been running and collecting data into the database for a few months. I really can't lose this data.
- I branched my code, installed EF5 with NuGet, and used EF Power Tools to generate my model from my database by right-clicking a new class library project, and selecting
Entity Framework | Reverse engineer code first
. - I was able to smoothly re-reference to my new project, convert my project to use the new DbContext instead of ObjectContext, and removed the EF4 class library that held my old model. The program works great!
Now, I want to try out automatic migrations, which I've had a tiny bit of experience with in Ruby on Rails. Here's what I did:
- Ran
Enable-Migrations
. Had a bit of trouble due to connection strings and which app.config was getting used, but eventually got it. However, this MSDN page says that this should have automatically generated the first migration to get me to the point I'm already at. It didn't. - Ran
Add-Migration InitialSchema
to accomplish what wasn't automatically done in step 1. This worked. - Added a property to one of my model objects, then attempted to run
Add-Migration AddSerialToLogEntries
, and was presented with:
Unable to generate an explicit migration because the following explicit migrations are pending: [201307190100268_InitialSchema]. Apply the pending explicit migrations before attempting to generate a new explicit migration.
Attempting to apply the migration on my existing database failed, which isn't surprising.
The other answers I mentioned above basically said that I'm out of luck, but like I said those were for older versions of the Entity Framework. Do I have any options here?
While writing this question, I thought I might be able to use SQL Server Management Studio to export my data to a SQL script, delete the entire database, let EF create it, then run the scripts to get my data back in... I will try that tomorrow when I have time, but I would like to hear if there are other options as I'm not 100% sure that would work and would hate to have any errors in the data inserted in the process.
In fact the
enable-migrations
command creates an initial migration only if your database has already been created with Code-First before in which case the database contains a__MigrationHistory
table. If this table does not exist (which is the case when you have an existing database that never has been created before with Code-First)enable-migrations
only creates theConfiguration
class. You have to calladd-migration
manually then to create the first migration class. So, the behaviour you have seen is expected.Generally the procedure to prepare an existing database for migrations is the following if you are using EF 5:
Call
enable-migrations
in package manager console. AMigrations
folder in your project and aConfiguration
class will be created.Open the
Configuration
class and setAutomaticMigrationsEnabled = false
in the constructor (if it isn't already by default).In package manager console call
"InitialSchema" is only an example name. You can name it like you want. A
<Timestamp>_InitialSchema
class will be created that derives fromDbMigration
. TheUp
andDown
methods in this class are empty due to the-IgnoreChanges
flag. Without this flag the class would contain a migration to add your whole model to the database which is not what you want since the existing database already contains the database schema.Run
update-database
in the package manager console. Because theUp
method is empty this update does nothing with your existing schema except it creates the__MigrationHistory
table (as a system table in your database) and adds the first record to this table that contains a model hash of your current EF model.Optional last step: If you prefer to work with automatic migrations open the
Configuration
class and setAutomaticMigrationsEnabled = true
in the constructor. If you want to proceed with code-based migrations leave the flagfalse
.At this point you can start to make changes to your model. Everytime you create a new migration with
add-migration
it will be based on your model before the modification and the migration class will only contain the necessary schema changes.I would suggest a slightly different approach that will leave you in a state where you can use migrations to create databases from scratch in your development environment:
Rather than calling
add-migration -IgnoreChanges InitialSchema
, try to get the generation of the initial schema migration to work. As you say, this should happen when you initially calledEnable-Migrations
. You could try pointing your database connection at a non-existent database to get this to work.As a result of this, your
InitialSchema
migration will contain the logic to create the database as it was at the point when you reverse-engineered it. You need to comment out the contents of theUp()
andDown()
until you've deployed to all the environments that already have an existing database.Then you can uncomment the contents of those methods and from then on, in your development environments you can drop the databases and recreate them using
and you'll have the full set of migrations in your
__MigrationHistory
table. This important because without it you won't be able to add new migrations in the future.