static void

Entity Framework Code First Migrations

Migrations (EF 4.3+)

You need to use NuGet's Package Manager Console. Get used to lots of typos.

Migrations via Database.SetInitializer

This generated Migrations.Configuration class is internal sealed- if you have a Database.SetInitializer with a outside the data project, you can change it to public. You don't need to do it if you configure in the app.config.
The MigrateDatabaseToLatestVersion initializer requires the DbContext and Configuration.

Database.SetInitializer(new MigrateDatabaseToLatestVersion<NorthwindContext, Migrations.Configuration>());

You can also configure the initializer in the app.config. (MSDN)

    <!--<context type="Data.Context.MyContext, Data" disableDatabaseInitialization="true" />-->
    <context type="Data.Context.MyContext, Data" disableDatabaseInitialization="false">
      <databaseInitializer type="System.Data.Entity.MigrateDatabaseToLatestVersion`2[[Data.Context.MyContext, Data], [Data.Migrations.Configuration, Data]], EntityFramework" />

Automatic Migrations

Once you have an initial migration, it tracks all changes so there are no further explicit migrations. Unless you have an existing database- you'll need to add-migration Initial -IgnoreChanges and update-migration to get the __migrationHistory table initialized. See below!
If you delete columns (=dropping a column) it throws an AutomaticDataLossException. You can suppress this in configuration (but consider it carefully...).

public Configuration()
    AutomaticMigrationsEnabled = true;
    //if you drop columns - consider this carefully...
    AutomaticMigrationDataLossAllowed = true;

Migration Code

You can't refer to the actual entities (you must follow the naming conventions or map manually). The overuse of lambda expressions is awkward, but you can do lower-level things like naming foreign key constraints and add indexes.

Extensibility is limited. You cannot define new MigrationOperations (DbMigration.AddOperation is private), only anonymous arguments to the existing builder methods.

public override void Up()
        cb => new
                Id = cb.Int(nullable: false, identity: true),
                ProductName = cb.String(nullable: false, maxLength: 20),
                CategoryId = cb.Int(nullable: true)
    .PrimaryKey(t => t.Id)
        t => t.CategoryId,
        name: "FK_Products_Category");

Migrations in Code

To run an update in code, use a DbMigrator.

public void RunUpdate(string connectionName)
    var configuration = new Configuration();
    //will use app.config/connectionStrings/add[@name=connectionName]
    configuration.TargetDatabase =
        new System.Data.Entity.Infrastructure.DbConnectionInfo(connectionName);
    var migrator = new DbMigrator(configuration);

Note that DbMigrator exposes three methods:

It won't let you AddMigration if there are pending migrations ("Apply the pending explicit migrations" error quoted above).
You can control the migration SQL generation. The hook is in Migrations.Configuration:

internal sealed class Configuration : DbMigrationsConfiguration<EntitiesContext>
    public Configuration()
        AutomaticMigrationsEnabled = false;
        SetSqlGenerator("System.Data.SqlClient", new CustomizedSqlGenerator());

The customized SQL generator must derive from MigrationSqlGenerator (or the SqlServer version SqlServerMigrationSqlGenerator) and then override the Generate methods.


You can take control of the scripts as long as you use insert the __MigrationHistory row. In the console use Update-Database -Script or script as follows:

public string WriteCreateDatabaseScript(DbContext context)
    var objectContext = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext;
    return objectContext.CreateDatabaseScript();
public string WriteMigrationScript()
    var configuration = new Configuration();
    var migrator = new DbMigrator(configuration);
    var scriptor =
        new System.Data.Entity.Migrations.Infrastructure.MigratorScriptingDecorator(migrator);
    //source, target migration names
    string script = scriptor.ScriptUpdate(null, null);
    return script;

Code First for an existing database

DbMigrator presumes it has control of the database. Since EF 6.1, you can have multiple contexts per database with the migration ContextKey (you cannot have overlapping tables - it's not true multi-tenant).

To port this to a remote database, use Update-Database -Script which should just contain the __MigrationHistory DDL and INSERT. From here on, Code First thinks it owns the database.
The script may fail: "Conversion failed when converting date and/or time from character string". This is because the migrationHistory insert is in the form '2012-03-03T15:07:35.431Z' and the database is set to compatibility with SqlServer 2000. You have to fix the databse: in SqlServer Management Studio, right click database, Properties-Options-Compatibility Level set to SqlServer 2005 (90) or above.