EF4.3 基于代码的迁移演练

原文地址:http://blogs.msdn.com/b/adonet/archive/2012/02/09/ef-4-3-code-based-migrations-walkthrough.aspx

原文名称:EF 4.3 Code-Based Migrations Walkthrough

准备工作

在开始之前,我们需要一个项目,以及一个 Code First 的模型,对于这次演示,我们使用典型的博客 Blog 和回复 Post 模型。

1. 创建新的 MigrationsCodeDemo 控制台应用程序

2. 为项目添加最新版本的 EntityFramework NuGet 包。

找到包管理器控制台。

运行 Install-Package EntityFramework 命令。

成功之后的项目文件如下:

创建初始的模型和数据库

1. 增加如下的 Model.cs 文件,代码定义了一个单个的 Blog 类表示我们的模型对象,BlogContext 类就是 EF Code First 的上下文。

using System.Data.Entity;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity.Infrastructure;

namespace MigrationsCodeDemo
{
public class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
}

public class Blog
{
public int BlogId { get; set; }
public string Name { get; set
; }
}
}

2. 现在我们已经有了一个模型,是时候进行一次数据访问了。使用如下的代码更新 Program.cs 文件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MigrationsCodeDemo
{
class Program
{
static void Main(string[] args)
{
using (var db = new BlogContext())
{
db.Blogs.Add(new Blog { Name = "Another Blog " });
db.SaveChanges();

foreach (var blog in
db.Blogs)
{
Console.WriteLine(blog.Name);
}
}
}
}
}

3. 运行程序,现在就可以在你本地的 SQLExpress 数据库中看到数据库了。

启用迁移

1. 在 Blog 类中增加一个 Url 属性。

    public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
}

2. 现在运行程序,会看到如下的异常。
未经处理的异常:  System.InvalidOperationException: The model backing the 'BlogContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

3. 正如异常建议,现在是开始使用 Code First 迁移的时候了,第一步是为我们的上下文启用迁移支持。

   在包管理器的控制台中执行命令:Enable-Migrations

4. 这个命令在项目中增加名为 Migrations 文件夹,文件夹中包含两个文件。

Configuration 类,这个类允许你配置你的上下文的迁移行为,在这个演示中,我们仅仅使用默认配置。

因为在这个项目中只有一个上下文,Enable-Migrations 自动填充应用的这个上下文。

201202171353373_InitialCreate.cs 中的 InitialCreate ,生成这个迁移是因为我们已经通过 Code First 创建了一个数据库。这个迁移中的代码表示我们已经创建的数据库,

 

namespace MigrationsCodeDemo.Migrations
{
using System.Data.Entity.Migrations;

public partial class InitialCreate : 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"
);
}
}
}

第一个迁移

你会使用到两个命令

Add-Migration,将会基于你对模型的修改创建一个迁移的脚手架。

Update-Database,将没有提交的修改提交到数据库。

1. 我们首先为我们新增加的 Url 属性创建一个迁移,Add-Migration 会帮我们完成这个工作,我们为这个迁移命名为:AddBlogUrl。

 执行:Add-Migration AddBlogUrl

项目中增加了一个文件 201202171413369_AddBlogUrl.cs

 

 

内容如下:

 

namespace MigrationsCodeDemo.Migrations
{
using System.Data.Entity.Migrations;

public partial class AddBlogUrl : DbMigration
{
public override void Up()
{
AddColumn("Blogs", "Url", c => c.String());
}

public override void Down()
{
DropColumn("Blogs", "Url"
);
}
}
}

3. 我们可以在这个迁移中编辑或者增加内容,但是现在看起来就很不错,让我们将这个迁移提交到数据库中。

执行: Update-Database

4. 现在的数据库中已经包含了 Url 列。

定制迁移

下面我们看看如何定制迁移。

1. 在代码中增加一个回复的类 Post,同时在 Blog 中增加一个评分属性。

using System.Data.Entity;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity.Infrastructure;

namespace MigrationsCodeDemo
{
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { 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; }
}
}

2. 使用 Add-Migration 命令创建一个迁移,命名为 AddPostClass。

3.  Code First Migrations 帮我们创建好了一个迁移,但是我们希望能增加如下的修改:

     首先,为 Posts.Title 增加一个唯一索引。

     增加一个非空的 Blogs.Rating 列,如果表中已经存在了数据,那么就将 CLR 默认的数据类型值赋予新增加的列 (Rating 是整数类型,应该就是 0), 但是,我们希望默认为 3, 这样已经存在的博客会有一个不错的评分。

namespace MigrationsCodeDemo.Migrations
{
using System.Data.Entity.Migrations;

public partial class AddPostClass : 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");
DropColumn("Blogs", "Rating");
DropTable("Posts"
);
}
}
}

4. 运行 Update-Database 提交到数据库,这次可以使用一个参数 -Verbose,以便可以看到生成的 SQL 脚本。

数据操作/定制 SQL

我们已经完成的迁移并没有修改或者移动任何数据,我们可以在迁移中的任何地点运行任意脚本。

1. 在模型上增加一个摘要 PostAbstrack 属性,然后,希望使用已经发布的内容来填充这个摘要属性。

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
; }
}

2. 创建一个迁移。

3. 修改生成的迁移文件,

namespace MigrationsCodeDemo.Migrations
{
using System.Data.Entity.Migrations;

public partial class AddPostAbstract : DbMigration
{
public override void Up()
{
AddColumn("Posts", "Abstract", c => c.String());

Sql("UPDATE Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");

}

public override void Down()
{
DropColumn("Posts", "Abstract"
);
}
}
}

4. 更新数据库之后,就会得到最新的数据了。使用 Verbose 参数可以看到提交的脚本。

posted @ 2013-01-08 16:25  e天下小熊  阅读(224)  评论(0编辑  收藏  举报