Entity Framework 5 Migrations: Setting up an initial migration and single seed of the database

Neil picture Neil · Nov 22, 2012 · Viewed 21k times · Source

I have an MVC4 app which I've recently upgraded to Entity Framework 5 and I am trying to move our database over to using migrations from the development style of dropping and creating each run.

Here's what I've done in my app start function.

protected void Application_Start()
{
    Database.SetInitializer(
        new MigrateDatabaseToLatestVersion< MyContext, Configuration >() );
    ...
}

I ran the Enable-Migrations command on my repositories project and I thought that this would create an initial migration file however the only file it created was Configuration

When I delete the database it creates it as expected via code first and seeds the database from the Configuration file. In the configuration file I changed all the Add() functions to AddOrUpdate()

However it runs the seed function in my Configuration file each time the website starts and duplicates all the seed data again and again.

I imagined that it would create an initial migration file as the blog I read suggested that it would and I could put the seed data in there but it didn't

Can anyone explain how I should be setting up DB in code so that it only seeds once?


LINK: The migrations blog post I followed


While this is quite interesting for using the EF migrate.exe I've since switched to using roundhouse for running migrations. I still use EF to scaffold my migrations based on the models but I wrote a little console app to write the migrations out to SQL files. I then use roundhouse to perform the migrations themselves through my rake build scripts. There's a little more process involved but it's much more stable than using EF to perform the migrations on the fly when the application starts up.

Answer

Jon P Smith picture Jon P Smith · Jan 4, 2013

This has proved to be a popular post so I have updated it in light of feedback from others. The main thing to know is that the Seed method in the Configuration class is run EVERY time the application starts, which isn't what the comment in the template method implies. See the answer from someone at Microsoft to this post about why that is - thanks to Jason Learmouth for finding that.

If you, like me, only want to run the database updates if there are any pending migrations then you need to do a bit more work. You can find that out if there are pending migrations by calling migrator.GetPendingMigrations(), but you have to do that in the ctor as the list of pending migrations is cleared before Seed method is called. The code to implement this, which goes in the Migrations.Configuration class is as follows:

internal sealed class Configuration : DbMigrationsConfiguration<YourDbContext>
{ 
    private readonly bool _pendingMigrations;

    public Configuration()
    {
        // If you want automatic migrations the uncomment the line below.
        //AutomaticMigrationsEnabled = true;
        var migrator = new DbMigrator(this);
        _pendingMigrations = migrator.GetPendingMigrations().Any();
    }

    protected override void Seed(MyDbContext context)
    {
        //Microsoft comment says "This method will be called after migrating to the latest version."
        //However my testing shows that it is called every time the software starts

        //Exit if there aren't any pending migrations
        if (!_pendingMigrations) return;

        //else run your code to seed the database, e.g.
        context.Foos.AddOrUpdate( new Foo { bar = true});
    }
}

I should point out that some people have suggested putting the seed code in the actual 'up' migration code. This works, but means you need to remember to put the seed code in each new migration and its pretty hard remember so I wouldn't do that. However if your seed changes with each migration then that might be the a good way to go.