若是使用的是 Code First 工做流,推荐使用 Code First 迁移改进应用程序的数据库架构。 迁移提供一组容许如下操做的工具:sql
下方演练将概述实体框架中的 Code First 迁移。 能够完成整个演练或跳到感兴趣的主题。 包含如下主题:数据库
开始使用迁移以前,须要会用到项目和 Code First 模型。 对于此演练,咱们将使用规范的“博客”和“帖子”模型。服务器
using System.Data.Entity; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data.Entity.Infrastructure; namespace MigrationsDemo { public class BlogContext : DbContext { public DbSet<Blog> Blogs { get; set; } } public class Blog { public int BlogId { get; set; } public string Name { get; set; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MigrationsDemo { 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); } } Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } } }
运行应用程序,随即会建立 MigrationsCodeDemo.BlogContext 数据库。架构
现可对模型进行更多更改。app
public string Url { get; set; }
若是要再次运行应用程序,则会收到一个 InvalidOperationException,指出“建立数据库后,支持‘BlogContext’上下文的模型已发生变化。请考虑使用 Code First 迁移更新数据库 (http://go.microsoft.com/fwlink/?LinkId=238269)”。框架
如异常状况所述,可开始使用 Code First 迁移。 第一步是启用上下文迁移。ide
在包管理器控制台中运行 Enable-Migrations 命令工具
此命令已将“迁移”文件夹添加到项目中。 此新文件夹包含两个文件:测试
配置类。 此类容许配置迁移对上下文的行为方式。 对于此演练,将只使用默认配置。 因为项目中只有一个 Code First 上下文,所以 Enable-Migrations 已自动填充此配置适用的上下文类型。ui
InitialCreate 迁移。 之因此生成此迁移,是由于在启用迁移以前,咱们已使用 Code First 建立了数据库。 已构建的迁移中的代码表示已在数据库中建立的对象。 在本演练中,即为具备 BlogId 和“名称”列的 Blog 表。 文件名包含时间戳,这样有助于排序。若是还没有建立数据库,则不会将此 InitialCreate 迁移添加到项目中。相反,第一次调用 Add-Migration 时,会将建立这些表的代码构建到新的迁移中。
使用 EF6 以前的版本时,只能使用一个 Code First 模型生成/管理数据库的架构。 这是由于每一个数据库的单个 __MigrationsHistory 表没法识别哪些项属于哪一个模型。
从 EF6 开始,配置类中包括 ContextKey 属性。 该属性充当每一个 Code First 模型的惟一标识符。 __MigrationsHistory 表中相应的列容许来自多个模型的项共享表。 默认状况下,此属性设置为上下文的彻底限定名称。
Code First 迁移具备两个须要用户了解的主要命令。
咱们须要构建迁移来处理添加的新 Url 属性。 Add-Migration 命令可为这些迁移命名,仅需调用 AddBlogUrl。
namespace MigrationsDemo.Migrations { using System; using System.Data.Entity.Migrations; public partial class AddBlogUrl : DbMigration { public override void Up() { AddColumn("dbo.Blogs", "Url", c => c.String()); } public override void Down() { DropColumn("dbo.Blogs", "Url"); } } }
现可编辑或添加到此迁移,但全部内容看起来都很合适。 使用 Update-Database 将此迁移应用到数据库。
MigrationsDemo.BlogContext 数据库现已更新,其中包含“博客”表中的 Url 列。
到目前为止,咱们已在未进行任何更改的状况下生成并运行了迁移。 如今咱们来看看如何编辑默认生成的代码。
public int Rating { 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; } }
public virtual List<Post> Posts { get; set; }
使用 Add-Migration 命令使 Code First 迁移提供对迁移的最佳猜想 咱们将调用此迁移 AddPostClass。
Code First 迁移出色的构建了这些更改,但咱们可能还须要作出一些更改:
namespace MigrationsDemo.Migrations { using System; using System.Data.Entity.Migrations; public partial class AddPostClass : DbMigration { public override void Up() { CreateTable( "dbo.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("dbo.Blogs", t => t.BlogId, cascadeDelete: true) .Index(t => t.BlogId) .Index(p => p.Title, unique: true); AddColumn("dbo.Blogs", "Rating", c => c.Int(nullable: false, defaultValue: 3)); } public override void Down() { DropIndex("dbo.Posts", new[] { "Title" }); DropIndex("dbo.Posts", new[] { "BlogId" }); DropForeignKey("dbo.Posts", "BlogId", "dbo.Blogs"); DropColumn("dbo.Blogs", "Rating"); DropTable("dbo.Posts"); } } }
已编辑的迁移准备就绪,因此咱们使用 Update-Database 来更新数据库。 此次指定 –Verbose 标志,以即可以看到 Code First 迁移正在运行的 SQL。
到目前为止,咱们已经介绍了不更改或移动任何数据的迁移操做,如今来看看须要移动数据的操做。 目前尚未对数据移动的原生支持,但咱们能够在脚本中的任何位置运行一些任意 SQL 命令。
namespace MigrationsDemo.Migrations { using System; using System.Data.Entity.Migrations; public partial class AddPostAbstract : DbMigration { public override void Up() { AddColumn("dbo.Posts", "Abstract", c => c.String()); Sql("UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL"); } public override void Down() { DropColumn("dbo.Posts", "Abstract"); } } }
已编辑的迁移一切正常,因此咱们可以使用 Update-Database 来更新数据库。 咱们将指定 –Verbose 标志,以即可以看到针对数据库运行的 SQL。
到目前为止,咱们一直在升级到最新迁移,但用户有时可能但愿升级/降级到特定迁移。
假设想在运行 AddBlogUrl 迁移后将数据库迁移到其以前的状态。 此时可以使用 –TargetMigration 切换为降级到此迁移。
此命令将为 AddBlogAbstract 和 AddPostClass 迁移运行 Down 脚本。
若是想要一直回退到空数据库,可以使用 Update-Database –TargetMigration: $InitialDatabase 命令。
若是另外一位开发人员但愿在其计算机上进行这些更改,则只需在咱们将更改签入源代码管理以后进行同步便可。 在得到咱们的新迁移后,他们只需运行 Update-database 命令便可在本地应用更改。 可是,若是想将这些更改推送到测试服务器以及最终的产品,则可能须要一个能够传递给 DBA 的 SQL 脚本。
Code First 迁移将运行迁移管道,但并不是是应用更改,而是将更改写入到 .sql 文件。 生成脚本后,将在 Visual Studio 中打开,以供查看或保存。
从 EF6 开始,若是指定 –SourceMigration $InitialDatabase,则生成的脚本将为“幂等”。 幂等脚本能够将当前任何版本的数据库升级到最新版本(或使用 – TargetMigration 升级到指定版本)。 生成的脚本包括检查 __MigrationsHistory 表的逻辑,而且仅应用之前未应用的更改。
若是要部署应用程序,则可能但愿应用程序在启动时自动升级数据库(经过应用各类挂起的迁移)。 能够经过注册 MigrateDatabaseToLatestVersion 数据库初始值设定项来执行此操做。 数据库初始值设定项仅包含一些用于确保正确设置数据库的逻辑。 第一次在应用程序进程中使用上下文时,会运行此逻辑 (AppDomain)。
以下所示,能够更新 Program.cs 文件,以在使用上下文(第 14 行)以前,为 BlogContext 设置 MigrateDatabaseToLatestVersion 初始化值设定项。 请注意,还须要为 System.Data.Entity 命名空间(第 5 行)添加 using 语句。
建立此初始值设定项的实例时,须要指定上下文类型 (BlogContext) 和迁移配置(配置)- 迁移配置是启用迁移时添加到“迁移”文件夹的类**。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Entity; using MigrationsDemo.Migrations; namespace MigrationsDemo { class Program { static void Main(string[] args) { Database.SetInitializer(new MigrateDatabaseToLatestVersion\<BlogContext, Configuration>()); 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); } } Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } } }
如今,每当应用程序运行时,它首先会检查其目标数据库是否为最新,若是不是,则会应用各类挂起的迁移。
from: https://docs.microsoft.com/zh-cn/ef/ef6/modeling/code-first/migrations/
有用的URl :https://blog.csdn.net/zzulishulei/article/details/76685915