EF Code First Migrations 官方Demo

https://msdn.microsoft.com/en-us/data/jj591621

 

一、建立初始模型和数据库

1、创建一个新的控制台程序 MigrationsDemo 

2、安装最新的 EntityFramework NuGet 程序包

打开程序包管理器控制台 -> 运行命令 Install-Package EntityFramework 

3、创建名为 Model.cs 的文件,代码如下,其中定义了一个组成领域模型的 Blog 类,和一个 EF Code First 上下文类 BlogContext 。

 1     using System.Data.Entity;
 2     using System.Collections.Generic;
 3     using System.ComponentModel.DataAnnotations;
 4     using System.Data.Entity.Infrastructure;
 5 
 6     namespace MigrationsDemo
 7     {
 8         public class BlogContext : DbContext
 9         {
10             public DbSet<Blog> Blogs { get; set; }
11         }
12 
13         public class Blog
14         {
15             public int BlogId { get; set; }
16             public string Name { get; set; }
17         }
18     }

4、更改 Program.cs 文件的代码

 1     using System;
 2     using System.Collections.Generic;
 3     using System.Linq;
 4     using System.Text;
 5 
 6     namespace MigrationsDemo
 7     {
 8         class Program
 9         {
10             static void Main(string[] args)
11             {
12                 using (var db = new BlogContext())
13                 {
14                     db.Blogs.Add(new Blog { Name = "Another Blog " });
15                     db.SaveChanges();
16 
17                     foreach (var blog in db.Blogs)
18                     {
19                         Console.WriteLine(blog.Name);
20                     }
21                 }
22 
23                 Console.WriteLine("Press any key to exit...");
24                 Console.ReadKey();
25             }
26         }
27     }

5、配置 App.config 中的数据库连接字符串(与本地SqlServer数据库连接)。

1 <configuration>
2   <connectionStrings>
3     <add name="BlogContext" connectionString="Data Source=.;Initial Catalog= BlogContext;Integrated Security=True" providerName="System.Data.SqlClient" />
4   </connectionStrings>
5 </configuration>

 6、运行程序,在SqlServer中自动生成数据库。

 

二、实现迁移

向 Blog 类添加 Url 属性

public string Url { get; set; }

如果直接运行程序,会报错。

实现上下文的迁移:打开程序包管理器控制台 -> 运行命令 Enable-Migrations

命令执行后,在项目中生成了一个 Migrations 文件夹,包含两个文件:Configuration 类,InitialCreate迁移。

 

多个模型指向同一个数据库

在 Configuration 文件中,包含了 ContextKey 属性,作为 Code First 模型的唯一识别符。

 

三、生成并运行迁移

Code First 迁移有两个主要命令:

Add-Migration :基于上次迁移后所作出的改变,搭建接下来的迁移支架。

Update-Database :将所有的待执行迁移应用到数据库

1、在程序包管理器控制台执行命令 Add-Migration AddBlogUrl  (AddBlogUrl  :Add-Migration 允许我们给这些迁移命名)。

2、在 Migrations 文件夹中,生成了AddBlogUrl  迁移,如下所示。

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

3、执行命令 Update-Database,数据库被更新(Blogs 表中包含了 Url 列)。

 

四、定制迁移

在 Blog 类中添加 Rating 属性

public int Rating { get; set; }

添加一个新的 Post 类

 1     public class Post
 2     {
 3         public int PostId { get; set; }
 4         [MaxLength(200)]
 5         public string Title { get; set; }
 6         public string Content { get; set; }
 7 
 8         public int BlogId { get; set; }
 9         public Blog Blog { get; set; }
10     }

在 Blog 类中添加 Posts 集合,来建立 Blog 和 Post 之间的关系

public virtual List<Post> Posts { get; set; }

执行命令 Add-Migration AddPostClass

但是,我们可能需要做一些改变:

1、为 Posts.Title 列添加唯一索引 (如代码22和29行所示)

2、添加一个不为空的 Blogs.Rating 列 (如代码24行所示设置默认值)

 1     namespace MigrationsDemo.Migrations
 2     {
 3         using System;
 4         using System.Data.Entity.Migrations;
 5         
 6         public partial class AddPostClass : DbMigration
 7         {
 8             public override void Up()
 9             {
10                 CreateTable(
11                     "dbo.Posts",
12                     c => new
13                         {
14                             PostId = c.Int(nullable: false, identity: true),
15                             Title = c.String(maxLength: 200),
16                             Content = c.String(),
17                             BlogId = c.Int(nullable: false),
18                         })
19                     .PrimaryKey(t => t.PostId)
20                     .ForeignKey("dbo.Blogs", t => t.BlogId, cascadeDelete: true)
21                     .Index(t => t.BlogId)
22                     .Index(p => p.Title, unique: true);
23 
24                 AddColumn("dbo.Blogs", "Rating", c => c.Int(nullable: false, defaultValue: 3));
25             }
26             
27             public override void Down()
28             {
29                 DropIndex("dbo.Posts", new[] { "Title" });
30                 DropIndex("dbo.Posts", new[] { "BlogId" });
31                 DropForeignKey("dbo.Posts", "BlogId", "dbo.Blogs");
32                 DropColumn("dbo.Blogs", "Rating");
33                 DropTable("dbo.Posts");
34             }
35         }
36     }

现在,迁移已编辑好,执行命令 Update-Database  –Verbose 

PS:加上 –Verbose 可查看 Code First Migrations 运行的SQL 

 

五、数据移动/定制SQL

添加 Post.Abstract 属性,稍后将从 Content 列中获取数据赋给 Abstract 

public string Abstract { get; set; }

执行命令 Add-Migration

将每一个post中的content 的前100个字符赋给Abstract (如第12行代码所示)

 1     namespace MigrationsDemo.Migrations
 2     {
 3         using System;
 4         using System.Data.Entity.Migrations;
 5         
 6         public partial class AddPostAbstract : DbMigration
 7         {
 8             public override void Up()
 9             {
10                 AddColumn("dbo.Posts", "Abstract", c => c.String());
11 
12                 Sql("UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");
13             }
14             
15             public override void Down()
16             {
17                 DropColumn("dbo.Posts", "Abstract");
18             }
19         }
20     }

执行命令 Update-Database  –Verbose 

 

六、迁移到特定版本(包括降级)

假设需要把数据库状态还原到运行AddBlogUrl 迁移之后,可以用TargetMigration

运行 Update-Database –TargetMigration: AddBlogUrl 

这个命令将运行 AddBlogAbstract 和 AddPostClass 的 Down script

如果要一路回滚到空数据库,则可执行 Update-Database –TargetMigration: $InitialDatabase

 

七、获取 SQL 脚本

 执行命令:

Update-Database –Script

Update-Database -Script -SourceMigration: $InitialDatabase -TargetMigration: AddPostAbstract 

如果不指定目标迁移,则使用最新一次迁移;如果不指定源迁移,则使用数据库的当前状态

 

生成幂等脚本(EF6以上)

 从EF6开始,如果指定-SourceMigration $ InitialDatabase,则生成的脚本将为“幂等”。幂等脚本可以将当前处于任何版本的数据库升级到最新版本(如果使用-TargetMigration则指定版本)。生成的脚本包括检查__MigrationsHistory表的逻辑,并仅应用以前未应用的更改。

 

八、程序启动时自动更新(初始化 MigrateDatabaseToLatestVersion

更改 Configuration.cs 文件,设置 AutomaticMigrationsEnabled = true

 1     using System.Data.Entity.Migrations;
 2 
 3     internal sealed class Configuration : DbMigrationsConfiguration<MigrationsDemo.BlogContext>
 4     {
 5         public Configuration()
 6         {
 7             AutomaticMigrationsEnabled = false;
 8             ContextKey = "MigrationsDemo.BlogContext";
 9         }
10 
11         protected override void Seed(MigrationsDemo.BlogContext context)
12         {            
14         }
15     }

更改 Program.cs 文件,设置 MigrateDatabaseToLatestVersion 

 1     using System;
 2     using System.Collections.Generic;
 3     using System.Linq;
 4     using System.Text;
 5     using System.Data.Entity;
 6     using MigrationsDemo.Migrations;
 7 
 8     namespace MigrationsDemo
 9     {
10         class Program
11         {
12             static void Main(string[] args)
13             {
14                 Database.SetInitializer(new MigrateDatabaseToLatestVersion<BlogContext, Configuration>());
15 
16                 using (var db = new BlogContext())
17                 {
18                     db.Blogs.Add(new Blog { Name = "Another Blog " });
19                     db.SaveChanges();
20 
21                     foreach (var blog in db.Blogs)
22                     {
23                         Console.WriteLine(blog.Name);
24                     }
25                 }
26 
27                 Console.WriteLine("Press any key to exit...");
28                 Console.ReadKey();
29             }
30         }
31     }

 

posted @ 2017-06-06 19:51  ztpark  阅读(409)  评论(0编辑  收藏  举报