Entity Framework – Migrations

Following on from my post of Code First with entity framework. Each time I wanted to make changes to the database I went through the process of dropping the database and then regenerating it. This is fine during the development phase and especially if there’s no data to reimport to it. But let’s look at an alternative to this and something more likely to be of use when amending an existing database with a changed schema.

Migration commands are used to generate change tracking files. The commands are run via Visual Studio using the Tools | Library Packager Manager | Package Manager Console.

So load up the Package Manage Console (if it’s not already running) in Visual Studio.

The first thing we need to do is enable migrations on the project. This basically sets up the migration configuration files etc. ready for you to start migrations. So run

Enable-Migrations

and you’ll see a Migrations folder added to your project as well as a Congiruations.cs file and an _InitialCreate.cs file (and associated designer.cs and .rex files).

If you first take a look at the Configurations.cs file you’ll see a pretty empty file which can be used to seed data or handle other migration configuration code.

The _InitialCreate.cs file is where the code exists for actually recreating the current database tables.

Okay, so now we want to make some actual changes to our database. So continuing to use the sample code from the Code First I need to add dimensions to the Planogram, so my new code will look like this (new code highlighted)

public class Planogram
{
   public int Id { get; set; }
   public string Name { get; set; }

   public double Width { get; set; }
   public double Height { get; set; }
   public double Depth { get; set; }

   public virtual ICollection<Product> Products { get; set; }
   public virtual Store Store { get; set; }
}

If we now write some code to populate the new fields and run our application we’ll get an InvalidOperationException stating that the model backing the database context has changed. In other words we’ve changed the model but the DB is not in sync. The exception kindly notes that we should consider using Code First Migrations to update the database. So that’s what we’ll do next (for completeness the new coe to create the Planogram is listed below)

using (StorePlanDatabase storePlanDatabase = new StorePlanDatabase())
{
   Planogram pegboard = new Planogram
   {
      Name = "Batteries Pegboard",
      Depth = 50,
      Height = 1000,
      Width = 800
   };
   storePlanDatabase.Planograms.Add(pegboard);
}

So now back to our Package Manager Console and we need to create a migrations script for the changes to the model and thus the changes required to bring the database into sync with the model. At the Package Manager Console command line type

Add-Migration PlanogramDimensions

PlanogramDimensions is the descriptive name we’re giving to these changes to the model. If you don’t enter a name you will be prompted for one. A new file _PlanogramDimensions.cs (and it’s associated Designer.cs and .resx) are created. If you take a look into this file you’ll see code specific to adding (and dropping) the new columns on the Planograms table.

At this point the database has not been updated, this has just created the required “patch” if you like. So now from the Package Manager Console run

Update-Database

This will run the migrations script and patch the db it will also run the seed data method from the configurations. If you now check the db you’ll find the Planograms table has the new Width, Height and Depth fields.