Lance Larsen - .NET Architect Madison Wisconsin

Entity Framework “Code First + Migration” 101

So for those who haven’t used Microsoft Entity Framework’s “Code First” approach to application development – it’s a very powerful approach that allows us developers to spin up a project with a database back end in record time!  Early on it had the distinct disadvantage that it didn’t allow for changes in your code to migrate to the database – but, as we will see, that feature has also matures and is pretty sweet now… :)

So where to start?

Open Visual Studio, click “New” –> “Project” –> “Console Application” and create your application…

imageAdd Entity Framework to the project.  We’ll do this by using “NuGet”.  Right-Click on the project, select “Manage NuGet Packages…”, enter “EntityFramework” ( usually right at the top ) and click “Install”.  This will add all of the “entity-goodness” to your project!

 

 

Right-Click on your project and click “Add” –> “Class…” –> name it “Model.cs” and insert the following code…

 

   1:  using System.Data.Entity;
   2:   
   3:  namespace CodeFirstConsole101
   4:  {
   5:      public class MyDatabaseContext : DbContext
   6:      {
   7:          //----------------------------------------------------------------------
   8:          // If you don't want your database to be named "MyDatabaseContext", then
   9:          //  enter the name you want, for example, in base("MyNewDatabase") inherited 
  10:          //  class.  Further, if you want to require that the location and type
  11:          //  of your database be explicitly defined in your App.config file - 
  12:          //  add the base("name=MyNewDatabase") - if it doesn't find it - it will
  13:          //  throw an exception letting us know.  The latter is my preference.
  14:          //----------------------------------------------------------------------
  15:          public MyDatabaseContext() : base("name=MyNewDatabase")
  16:          {
  17:          }
  18:   
  19:          public DbSet<Widget> Widgets { get; set; }
  20:      }
  21:   
  22:      /// <summary>
  23:      /// Our Widget class that will be added to the database
  24:      /// </summary>
  25:      public class Widget
  26:      {
  27:          public int Id { get; set; }
  28:          public string Name { get; set; }
  29:      }
  30:  }

Then in your Program.cs file, insert the following…
 

   1:  using System;
   2:   
   3:  namespace CodeFirstConsole101
   4:  {
   5:      class Program
   6:      {
   7:          static void Main(string[] args)
   8:          {
   9:              using (var db = new MyDatabaseContext())
  10:              {
  11:                  //----------------------------------------------------------------------
  12:                  // Add a new Widget
  13:                  //----------------------------------------------------------------------
  14:                  db.Widgets.Add(new Widget { Name = "My New Widget!" });
  15:                  db.SaveChanges();
  16:   
  17:                  //----------------------------------------------------------------------
  18:                  // Loop through the widgets from the Database
  19:                  //----------------------------------------------------------------------
  20:                  foreach (var widget in db.Widgets)
  21:                  {
  22:                      Console.WriteLine(widget.Name);
  23:                  }
  24:              }
  25:   
  26:              Console.WriteLine("Press Any Key...");
  27:              Console.ReadKey();
  28:          }
  29:      }
  30:  }

If you run the project now – since we added the following line…
  

   1:  public MyDatabaseContext() : base("name=MyNewDatabase")

We’d get an exception – letting us know that we didn’t include the connectionString value in our App.config – which is what we want.  If we didn’t use the “name=” then EF ( Entity Framework ) would create the database either in your local SQLEXPRESS instance, or in your LocalDb if SQLEXPRESS wasn’t installed / running.  I prefer to be explicit when creating the Database – so you can add one of the following to your App.config.

To store your data in a local SQL Server Compact database (*.sdf) – add…
 

<connectionStrings>
  <add name="MyNewDatabase"
        providerName="System.Data.SqlServerCe.4.0"
        connectionString="Data Source=MyNewDatabase.sdf"/>
</connectionStrings>

Or to create a full SQL Server instance ( substituting in your own Data Source ) – add…
 

<connectionStrings>
  <add name="MyNewDatabase" 
       connectionString="Data Source=K9;Initial Catalog=MyNewDatbase;Integrated Security=True;MultipleActiveResultSets=True"
       providerName="System.Data.SqlClient" />
</connectionStrings>

imageimageRUN IT!  See that we get “My New Widget!”… Run it again!  We see “My New Widget!” twice – that means we’re storing data… Cool!

 

 

imageimageIf we spin up SQL Server Manager – we in fact can see that it did create it as expected!  And there is our data, very nice…

 

 

 

 

 

 

What if my “Code First” classes change?

Excellent question!  This is where “Migration” comes into play…

Say we want to add an addition “Color” attribute to our Widget class, as follows…
  

   1:      public class Widget
   2:      {
   3:          public int Id { get; set; }
   4:          public string Name { get; set; }
   5:          public string Color { get; set; }
   6:      }

imageIf we run our application now – we get the following error: “The model backing the ‘MyDatabaseContext’ context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).”

Going to that link, gives us some great info…

And to solve the problem we do the following, click “View” –> “Other Windows” –> “Package Manager Console” – this opens the panel on the bottom of Visual Studio – and at the “PM>” prompt, enter “Enable-Migrations”.  Giving us back the message, “Code First Migrations enabled for project CodeFirstConsole101.”

In our project we now see the “Migrations” folder created for us – and this is where we will see all of the database migration scripts – both for pushing out and for rolling back changes.

image

If you open up the file ending in “_InitialCreation.cs” – you’ll see that this is ( shock! gasp! ) our initial database creation info. :)
 

   1:  namespace CodeFirstConsole101.Migrations
   2:  {
   3:      using System;
   4:      using System.Data.Entity.Migrations;
   5:      
   6:      public partial class InitialCreate : DbMigration
   7:      {
   8:          public override void Up()
   9:          {
  10:              CreateTable(
  11:                  "dbo.Widgets",
  12:                  c => new
  13:                      {
  14:                          Id = c.Int(nullable: false, identity: true),
  15:                          Name = c.String(),
  16:                      })
  17:                  .PrimaryKey(t => t.Id);
  18:              
  19:          }
  20:          
  21:          public override void Down()
  22:          {
  23:              DropTable("dbo.Widgets");
  24:          }
  25:      }
  26:  }

Back in your “Package Manager Console” window – enter “Add-Migration Update1” – where “Update1” can be anything such as “UpdateWidgetForColor” – the latter is certainly more descriptive.  Go with that next time…
 

   1:  namespace CodeFirstConsole101.Migrations
   2:  {
   3:      using System;
   4:      using System.Data.Entity.Migrations;
   5:      
   6:      public partial class Update1 : DbMigration
   7:      {
   8:          public override void Up()
   9:          {
  10:              AddColumn("dbo.Widgets", "Color", c => c.String());
  11:          }
  12:          
  13:          public override void Down()
  14:          {
  15:              DropColumn("dbo.Widgets", "Color");
  16:          }
  17:      }
  18:  }

imageAgain in the “Package Manager Console” – enter “Update-Database” – and it will apply the Up() method in the file above! That is pretty sweet! 

Look at our database, yup – the “Color” column is there!

Run our application – no exceptions!

And we’re done.

In conclusion, this is obviously a very simple example – but shows the immense POWER that this gives us.

Good Coding!

 
Comments

Hi Lance, Nice and to the point demo, thanks!

Leave a Reply