Entity Framework 6 – Enable Migrations

In a previous post I tested Entity Framework 6 Code First. In a production environment it is more than probable that we would need to make changes to our Model. E.g. We could need a new property.

Using EF and code first I would expect a way to add this property to my Entity class and somehow apply this change to my database. This is what I am going to test and share in this post.

As a start point of this post I will use the model created here: Entity Framework 6 – Code First.

We have already the entity Recipe in our model, and now we would like to add a simple new property type string, to store the recipe description.

public class Recipe
{
    // Primary Key
    public int RecipeId { getset; }
 
    // EF needs the virtual attribute to enable Lazy loading 
    public virtual List<Food> Ingredients { getset; }
 
    // New property with the description of the recipe
    public string Description { getset; }
}

If we run now the application this exception will appears:

image

Enable EF Code first migrations

  • Run the Enable-Migrations command in Package Manager Console

The output should be something similar to:

PM> Enable-Migrations
Checking if the context targets an existing database…
Detected database created with a database initializer. Scaffolded migration ‘201407242003173_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 CodeFirstAzureTest.

The command created a “Migrations” folder in my project with two classes:

  • Configuration: Migration options and Seed method to populate the database with data
namespace CodeFirstAzureTest.Migrations
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;
 
    internal sealed class Configuration : DbMigrationsConfiguration<CodeFirstAzureTest.FoodContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            ContextKey = "CodeFirstAzureTest.FoodContext";
        }
 
        protected override void Seed(CodeFirstAzureTest.FoodContext context)
        {
            //  This method will be called after migrating to the latest version.
 
            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
        }
    }
}
  • InitialCreate: Migrations work using steps to migrate up or down from one to other version, this method contains the Up and Down methods.  As this is the initial state the Up method creates completely the initial version of the database, the Down method would drop all tables. In future migrations each state should contains in this methods the required actions to migrate the current version up or down.
namespace CodeFirstAzureTest.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
    
    public partial class InitialCreate : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.Foods",
                c => new
                    {
                        FoodId = c.Int(nullable: false, identity: true),
                        Name = c.String(),
                        ExpireDate = c.DateTime(nullable: false),
                        StillInFridge = c.Boolean(nullable: false),
                        Recipe_RecipeId = c.Int(),
                    })
                .PrimaryKey(t => t.FoodId)
                .ForeignKey("dbo.Recipes", t => t.Recipe_RecipeId)
                .Index(t => t.Recipe_RecipeId);
            
            CreateTable(
                "dbo.Recipes",
                c => new
                    {
                        RecipeId = c.Int(nullable: false, identity: true),
                    })
                .PrimaryKey(t => t.RecipeId);
            
        }
        
        public override void Down()
        {
            DropForeignKey("dbo.Foods""Recipe_RecipeId""dbo.Recipes");
            DropIndex("dbo.Foods"new[] { "Recipe_RecipeId" });
            DropTable("dbo.Recipes");
            DropTable("dbo.Foods");
        }
    }
}

Add migration

There are two important migration commands that we should now:

  • Add-Migration <migration_name>: Define a new migration scanning the changes made in code.
  • Update-Database: Apply pending migrations to the database.

Let’s define a new migration and inspect the result, just run Add-Migration RecipeDescription in Package Manage Console:

The Designer Code for this migration file includes a snapshot of your current Code First model. This snapshot is used to calculate the changes to your model when you scaffold the next migration. If you make additional changes to your model that you want to include in this migration, then you can re-scaffold it by running ‘Add-Migration RecipeDescription’ again.

Perfect! A new class with the name RecipeDescription has been created and it contains the Up and Down methods with the changes required to migrate from and to the previous version of the database to this one.

namespace CodeFirstAzureTest.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
    
    public partial class AddDescription : DbMigration
    {
        public override void Up()
        {
            AddColumn("dbo.Recipes""Description", c => c.String());
        }
        
        public override void Down()
        {
            DropColumn("dbo.Recipes""Description");
        }
    }
}

Apply migration to database

To finish just run the Update-Database command and hopefully the table Recipe of our database should contains a new column “Description”…

Run Update-Database in Package Manage Console:

Specify the ‘-Verbose’ flag to view the SQL statements being applied to the target database.
Applying explicit migrations: [201407261630417_AddDescription].
Applying explicit migration: 201407261630417_AddDescription.
Running Seed method.

Perfect! Our database was updated:

image

Entity Framework migrations work out-of-the-box and is really easy to use and intuitive. I can’t wait to inspect more related advanced topics in my next post…

Advertisement

Your feedback is important...

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.