InitialCreate migration and why is it important
By Mirek on (tags: Entity Framework, migrations, categories: architecture, tools, code)Entity Framework migrations is indeed a great feature. It makes you don’t need to worry about the database schema updates almost at all. There are however few things you must know to properly understand and use EF migrations. This post describes few of those things.
Usually when you start a new project which makes use of Entity Framework and you starts developing it with a defaults settings the CreateDatabaseIfNotExists database initializer is used. This is fine as long as you do not change the database schema so domain model or you do not need to update any existing database schema.
Otherwise you would want to enable database migrations on a project so the EF will handle db schema updates for you. And here we came to the crucial thing of this post. After enabling database migrations you need to create an initial migration first. Since your database has already a certain structure and since after enabling migrations you cannot use database initializers any more, there will be a problem when you want to start your app and auto create the database for you. The initial migration contains information about the database schema up to the actual moment. It will create all tables and other related stuff on empty new database.
Ok lets see how to do it. We have a Core library where we have our domain model and EF related classes including DbContext. We also have a simple WPF application which consumes Core lib. Assume we are in the moment that changes to the domain model are necessary. Before we introduce those changes to the model we must enable EF migrations. In Package Manager Console we select the Core project where our DbContext class is defined and type in
Enable-Migrations
We should get similar message
Checking if the context targets an existing database...
Detected database created with a database initializer. Scaffolded migration '201410091230538_InitialCreate' corresponding to existing database. To use an automatic migration instead, delete the Migrations folder and re-run Enable-Migrations specifying the -EnableAutomaticMigrations parameter.
Code First Migrations enabled for project Core.
If everything went ok we should get a additional folder called Migrations where the initial migration and configuration class are stored. The initial migration should be scaffolded to create a complete current database schema.
public partial class InitialCreate : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Products",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(),
EAN = c.String(nullable: false),
Quantity = c.Int(nullable: false),
})
.PrimaryKey(t => t.Id);
}
public override void Down()
{
DropTable("dbo.Products");
}
}
However you can run into a situation that the InitialCreate migration is not created. This is usually because the __MigrationHistory is messed up. Then the only hope is to explicitly trigger creation of initial migration. However the messed up database cannot be uptated.
First you have to clear the __MigrationHistory table (with use of ex. Sql Server Management Studio). Then go to Package Manager Console and type
Add-Migration InitialCreate
and the initial migration should be created for you. Delete your current database and from console type
Update-Database
Fresh new database should be created for you and now you can modify your domain model and add further migrations.
One thing you should notice is that those are actually not an automatic migrations yet. That means starting application won’t update database by default. This is because we didn’t set the automatic migration. It can be also done in configuration class
internal sealed class Configuration : DbMigrationsConfiguration<Core.AppContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(Core.AppContext context)
{
}
}
First we must copy the migrate.exe tool to the directory where our Core library resides. It must be the library which contains the migrations. Then we can simply update the database with one simple line
migrate.exe Core.dll /startupConfigurationFile="TestMigrations.exe.config"
as a startupConfigurationFile we provide a config file of our application which contains a connection string.
Applying explicit migrations: [201410091546422_SetNameRequired].
Applying explicit migration: 201410091546422_SetNameRequired.
Running Seed method.
Our database gets latest updates. Migrate.exe allows to update database up and down to specific migration too.
More about Entity Framework migrations here and about manual migrations using migrate.exe here.