The official source of information on Managed Providers, DataSet & Entity Framework from Microsoft
The information in this post is out of date.
Visit msdn.com/data/ef for the latest information on current and past releases of EF.
For Code First Migrations see http://msdn.com/data/jj591621
We have released the fourth preview of our migrations story for Code First development; Code First Migrations Beta 1. This release includes a preview of the developer experience for incrementally evolving a database as your Code First model evolves over time.
This post will provide an overview of the functionality that is available inside of Visual Studio for interacting with migrations. We will focus on the ‘no-magic’ workflow for using migrations. In this workflow each change is written out to a code-based migration that resides in your project. There is a separate Code First Migrations: Beta 1 ‘With-Magic’ Walkthrough that shows how this same set of changes can be applied by making use of automatic migrations.
This post assumes you have a basic understanding of the Code First functionality that is included in EF 4.2, if you are not familiar with Code First then please complete the Code First Walkthrough.
Before we start using migrations we need a project and a Code First model to work with. For this walkthrough we are going to use the canonical Blog and Post model.
using System.Data.Entity; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data.Entity.Infrastructure; namespace Beta1Demo { public class BlogContext : DbContext { public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<IncludeMetadataConvention>(); } } public class Blog { public int BlogId { get; set; } public string Name { get; set; } } }
Now that we have a Code First model let’s get Code First Migrations and configure it to work with our context.
namespace Beta1Demo.Migrations { using System; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Linq; internal sealed class Configuration : DbMigrationsConfiguration<BlogContext> { public Configuration() { AutomaticMigrationsEnabled = false; // Seed data: // Override the Seed method in this class to add seed data. // - The Seed method will be called after migrating to the latest version. // - You can use the DbContext.AddOrUpdate() helper extension method to avoid creating // duplicate seed data. E.g. // // myContext.AddOrUpdate(c => c.FullName, // new Customer { FullName = "Andrew Peters", CustomerNumber = 123 }, // new Customer { FullName = "Brice Lambson", CustomerNumber = 456 }, // new Customer { FullName = "Rowan Miller", CustomerNumber = 789 } // ); // } } }
Code First Migrations has two commands that you are going to become familiar with. Add-Migration will scaffold the next migration based on changes you have made to your model. Update-Database will apply any pending changes to the database.
namespace Beta1Demo.Migrations { using System.Data.Entity.Migrations; public partial class MyFirstMigration : DbMigration { public override void Up() { CreateTable( "Blogs", c => new { BlogId = c.Int(nullable: false, identity: true), Name = c.String(), }) .PrimaryKey(t => t.BlogId); } public override void Down() { DropTable("Blogs"); } } } .
So far we’ve generated and run a migration without making any changes. Now let’s look at editing the code that gets generated by default.
public class Blog { public int BlogId { get; set; } public string Name { get; set; } public int Rating { get; set; } public List<Post> Posts { get; set; } } public class Post { public int PostId { get; set; } [MaxLength(200)] public string Title { get; set; } public string Content { get; set; } public int BlogId { get; set; } public Blog Blog { get; set; } }
namespace Beta1Demo.Migrations { using System.Data.Entity.Migrations; public partial class MySecondSetOfChanges : DbMigration { public override void Up() { CreateTable( "Posts", c => new { PostId = c.Int(nullable: false, identity: true), Title = c.String(maxLength: 200), Content = c.String(), BlogId = c.Int(nullable: false), }) .PrimaryKey(t => t.PostId) .ForeignKey("Blogs", t => t.BlogId, cascadeDelete: true) .Index(t => t.BlogId) .Index(p => p.Title, unique: true); AddColumn("Blogs", "Rating", c => c.Int(nullable: false, defaultValue: 3)); } public override void Down() { DropIndex("Posts", new[] { "BlogId" }); DropForeignKey("Posts", "BlogId", "Blogs", "BlogId"); DropColumn("Blogs", "Rating"); DropTable("Posts"); } } }
So far we have just looked at migration operations that don’t change or move any data, now let’s look at something that needs to move some data around. There is no native support for data motion yet, but we can run some arbitrary SQL commands at any point in our script.
public class Post { public int PostId { get; set; } [MaxLength(200)] public string Title { get; set; } public string Content { get; set; } public string Abstract { get; set; } public int BlogId { get; set; } public Blog Blog { get; set; } }
namespace Beta1Demo.Migrations { using System.Data.Entity.Migrations; public partial class AddPostAbstract : DbMigration { public override void Up() { AddColumn("Posts", "Abstract", c => c.String()); Sql("UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL"); } public override void Down() { DropColumn("Posts", "Abstract"); } } }
Our edited migration looks good, so let’s use Update-Database to bring the database up-to-date. We’ll specify the –Verbose flag so that we can see the SQL being run against the database.
So far we have always upgraded to the latest migration, but there may be times when you want upgrade/downgrade to a specific migration.
This command will run the Down script for our ‘AddBlogAbstract’ and ‘MySecondSetOfChanges’ migrations. If you want to roll all the way back to an empty database then you can use the Update-Database –TargetMigration:"0" command.
Now that we have performed a few iterations on our local database let’s look at applying those same changes to another database.
If another developer wants these changes on their machine they can just sync once we check our changes into source control. Once they have our new migrations they can just run the Update-Database command to have the changes applied locally. However if we want to push these changes out to a test server, and eventually production, we probably want a SQL script we can hand off to our DBA.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="MySecondDatabase" providerName="System.Data.SqlClient" connectionString="Server=.\SQLEXPRESS;Database=AnotherDatabase;Trusted_Connection=True;"/> </connectionStrings> </configuration>
In this walkthrough you saw how to scaffold, edit and run code-based migrations to upgrade and downgrade your database. You also saw how to get a SQL script that represents the pending changes to a database.
As always, we really want your feedback on what we have so far, so please try it out and let us know what you like and what needs improving.
Rowan Miller Program Manager ADO.NET Entity Framework