EF - Moving from AutomaticMigrations to Manual Mig

2019-03-15 12:13发布

问题:

End of long day of testing various scenarios where I don't have to recreate a production database...

We started off with EF, and didn't get wise enough during development to move from automatic migrations to named migrations. Now I'm trying to rewind the clock, and create an initial migration that aligns with the production database.

  1. Is this possible to align a model has with an automatic migration has in the migration table?
  2. Should I just create an empty migration to get started with named migrations? My only problem with this is how to create the DB when a new developer joins... I could simply restore the db, and then apply migrations, but that ruins a beautiful EF migration story!
  3. Delete the production DB, create, and write a script to re-import the data (sounds hacky).

Another wrinkle - the DB was created with EF5, and we are now developing with EF6.

Thanks in advance for your help.

回答1:

It should be possible:

  1. Delete the __MigrationHistory table
  2. Delete any migrations in your project
  3. Disable automatic migrations in your migrations configuration class
  4. Add-Migration InitialCreate
  5. Update-Database -Script
  6. Execute the portion of the script that creates the __MigrationHistory table and inserts a row into it
  7. Repeat steps 1 & 6 for any other existing databases

I also strongly recommend reading Code First Migrations in Team Environments.



回答2:

If you don't like step 7 of bricelam's answer. Then keep reading.

Because upgrading from automatic migrations to manual can also be automated. And you don't need to delete the migrationhistory table like bricelam says.

In this case I assume you have one development machine, and multiple other (development) machines where databases already exist.

  1. On your development machine you move your database into a safe location (keeping it safe to test your automatic upgrade procedure). (You might want to make sure your code is in the same exact state as all the database which you want to upgrade).

  2. Delete any migrations in your project (you should't have any yet)

  3. Disable automatic migrations in your migrations configuration class

  4. Add-Migration InitialCreate

  5. Put a backup (copy!) of your database back into place

  6. On startup of your application (or your upgrade app) you do something like:

        using (var db = new YourDatabaseContext())
        {
            InitialCreate.SkipInitialCreate = db.Database.Exists();
        }
    

And in your InitialCreate you add something like:

    public static bool SkipInitialCreate = false;

    public override void Up()
    {
        // Skip initial create
        if (SkipInitialCreate)
            return;

This assumes that if a database exists it has the same structure as the one you had on your dev machine. Of course this could be way more complex than that for you. For more control you could inspect DbMigrator object for your config, and skip more than one migration. (would have been nice if you could query the hash of the model in the DbMigrator...)

  1. After the code in step 4 add something like:

        var configuration = new YourDatabaseConfiguration();
        var migrator = new DbMigrator(configuration);
        migrator.Update();
    
  2. Start your application on your dev machine to test the upgrade. Your history table should have an automaticmigration record and a initialcreate record.

  3. If everything works out you should be able to simple deploy and run the app on machines where the db already exists.

One very important aspect (and maybe the reason bricelam says you needed to delete the history table) is that if the AutomaticMigration record in that table is newer than one of your manual migrations you are going to have a Bad time. Because the migrator uses the dates to sort out the work it needs to do.

So if there are systems out there still automatically upgrading to the newest auto-upgrade model, then you are in a bit of a pickle.