Entity Framework code first migrations

In this blog we will describe the options on how to run Entity framework code first migrations and advantages and disadvantages of each approach. For reading this blog I assume that you already have some basics understanding of code first in Entity framework.

One of the important things when running migrations is to insert some initial data. In our projects we usually insert an admin user and some default settings data and on this point we had first problems. If you have experience creating migrations you noticed that a Configuration.cs file was automatically created in Migrations folder. In this file you can override Seed method with initial data or some test data as shown in most examples on the web.

internal sealed class Configuration : DbMigrationsConfiguration<DbContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(DbContext context)
    {
    }
}

The problem is that Seed method is called always when running migrations. For example if you created first migration called InitialCreate which creates database and then you have made some changes to models and created another migration (or more), when you run migrations the seed method will execute again. There is no method that can be overridden and that will run only first time you create database (or run migrations).

First solution was to create a migration that is actually not a migration but it inserts initial data. When we tried this approach I found more cons that pros. First of all you cannot access DbContext and you have to insert data using plain sql commands. Another problem is if you use Identity framework you need access to DbContext to create users and nevertheless migrations are primary meant to deal with migrations and not with inserting some data into database.

Another solution is to check database if initial data were inserted or in our opinion the best solution is that Seed method checks if the first (initial) migration already run. This can be done with following code:

internal sealed class Configuration : DbMigrationsConfiguration<DbContext>
{
    private readonly bool _isInitialCreate;

    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        var migrator = new DbMigrator(this);
        _isInitialCreate = migrator.GetPendingMigrations().Any(x => x.Contains("InitialCreate"));
    }

    protected override void Seed(DbContext context)
    {
        if (!_isInitialCreate)
            return;

        InitialSeed.Seed(context);

        if (context.Database.Connection.ConnectionString.Contains("LocalDb"))
        {
            TestSeed.Seed(context);//Init test data
        }
    }
}

Note: Watch out how you run migrations with the Configuration above as you can create infinite loop if you would run migrations automatically when DbContext is created.

To run migrations with initial seed automatically (we do not suggest doing it) the code below gives an example how to do it:

public ApplicationDbContext() : base("DefaultConnection")
{
    if (!Database.Exists())
    {
        System.Data.Entity.Database.SetInitializer(new CreateDatabaseIfNotExists<ApplicationDbContext>());
        InitialSeed.Seed(this);
    }
    else
    {
        System.Data.Entity.Database.SetInitializer(
            new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());
    }
}

To explain the code above. The first initializer creates database if it does not exists. This means that it runs all migrations and after it we insert inital data to database. After finished it always check for new migrations in second initializer.

Note: If you have overridden seed method in Configuration it will run after every migration. You cannot use new DbMigrator(this) as it would create infinite loop. Disadvantage of this method is that it checks migrations every time DbContext is created which is not optimal.

In our opinion the best way to deal with migrations is by running them manually. Since migrations are not something you must run every five minutes. To run them manually (which is written in a lot of examples) run the following command in Package Manager Console Update-Database.

More about running migrations on different platforms can be found here. At the end of the article there is a section "Advanced Migrations Scenarios" that describes how to run migrations on server from command prompt. I suggest that you follow this link.

NOTE: If you are using Entity framework 6.1.3 you may run into problems that your config file would not be selected. The solution is described on the following link.