自动迁移允许你使用 Code First 迁移,而无需在项目中每次更改都创建一个代码文件。 并非所有更改都可以自动进行应用 - 例如,列重命名需要使用基于代码的迁移。
注意
本文假设您知道如何在基本场景下使用 Code First 迁移。 如果你不知道,则需要先阅读 Code First 迁移,再继续。
针对团队环境的建议
可以交错执行自动迁移和基于代码的迁移,但在团队开发场景中不建议这样做。 如果你是使用源代码控制的开发人员团队的一员,则应使用纯自动迁移或纯基于代码的迁移。 鉴于自动迁移的局限性,我们建议在团队环境中使用基于代码的迁移。
生成初始模型和数据库
在开始使用迁移之前,我们需要一个项目和一个 Code First 模型来进行工作。 对于本次讲解,我们将使用规范的博客和帖子模型。
- 创建新的 MigrationsAutomaticDemo 控制台应用程序
- 将最新版本的 EntityFramework NuGet 包添加到项目中
- “工具”–>“库包管理器”–>“包管理器控制台”
- 运行 Install-Package EntityFramework 命令
- 添加 Model.cs 文件,其代码如下所示。 此代码定义了一个 Blog 类,它构成我们的域模型;同时定义了一个 BlogContext 类,作为我们的 Entity Framework Code First 上下文。
using System.Data.Entity;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity.Infrastructure;
namespace MigrationsAutomaticDemo
{
public class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
}
}
- 现在我们拥有一个模型,可用它执行数据访问操作。 更新 Program.cs 文件,其代码如下所示。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MigrationsAutomaticDemo
{
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();
}
}
}
运行您的应用程序,您将看到为您创建了一个 MigrationsAutomaticCodeDemo.BlogContext 数据库。
启用迁移
现可对模型进行更多更改。
- 将 Url 属性引入“博客”类。
public string Url { get; set; }
如果要再次运行应用程序,则会收到一个 InvalidOperationException,指出“创建数据库后,支持‘BlogContext’上下文的模型已发生变化。请考虑使用 Code First 迁移更新数据库 (http://go.microsoft.com/fwlink/?LinkId=238269)。
正如异常所指出的,是时候开始使用 Code First 迁移。 由于我们想要使用自动迁移,因此我们将指定 –EnableAutomaticMigrations 开关。
在包管理器控制台中运行 Enable-Migrations –EnableAutomaticMigrations 命令 此命令已向项目添加“Migrations”文件夹。 此新文件夹包含一个文件:
配置类。 此类允许您配置迁移功能在您上下文中的工作方式。 对于此演练,将只使用默认配置。 由于项目中只有一个 Code First 上下文,因此 Enable-Migrations 已自动填充此配置适用的上下文类型。
第一次自动迁移
Code First 迁移具有两个需要用户了解的主要命令。
- Add-Migration 将基于自上次迁移创建以来对模型所做的更改来构建下一次迁移
- Update-Database 将会把所有挂起的迁移应用到数据库
我们将避免使用 Add-Migration(除非确实需要),而是专注于让 Code First 迁移自动计算并应用更改。 使用 Update-Database 命令,以便通过 Code First 迁移将我们模型中的更改(新的 Blog.Url 属性)推送到数据库。
- 在包管理器控制台中运行 Update-Database 命令。
MigrationsAutomaticDemo.BlogContext 数据库现已更新,已在“Blogs”表中加入“Url”列。
第二次自动迁移
让我们进行另一项更改,让 Code First Migrations 自动为我们将更改推送到数据库。
- 同时添加一个新的“帖子”类
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; }
}
- 此外,还需要将“Posts”集合添加到“Blog”类中,以形成“Blog”和“Post”之间关系的另一端。
public virtual List<Post> Posts { get; set; }
现在使用 Update-Database 更新数据库。 为了让你可以看到 Code First 迁移运行的 SQL 语句,这次我们指定 –Verbose 标志。
- 在包管理器控制台中运行 Update-Database –Verbose 命令。
添加基于代码的迁移
现在,让我们看看我们可能想要使用基于代码的迁移的一个场景。
- 为“Blog”类添加 Rating 属性
public int Rating { get; set; }
可只运行 Update-Database 以将这些更改推送到数据库。 但是,我们添加了一个不可为 null 的 Blogs.Rating 列,如果表中存在任何现有数据,它将被分配新列的数据类型的 CLR 默认值(Rating 是整数,因此将为“0”)。 但我们要将默认值指定为 3,以便“博客”表中的现有行以合适的分级开始。 使用 Add-Migration 命令将此更改写入基于代码的迁移中,以便我们可以对其进行编辑。 Add-Migration 命令允许我们为这些迁移命名,我们就将其称为 AddBlogRating。
- 在包管理器控制台中运行 Add-Migration AddBlogRating 命令。
- 在“Migrations”文件夹中,我们现在有一个新的 AddBlogRating 迁移。 迁移文件名以时间戳作为前缀,这样有助于排序。 编辑生成的代码,为 Blog.Rating 指定默认值 3(下面代码中的第 10 行)
迁移还有一个代码隐藏文件,该文件可捕获某些元数据。 通过此元数据,Code First 迁移可以复制我们在此基于代码的迁移之前执行的自动迁移。 如果其他开发人员想要运行迁移,或者需要部署应用程序,这一点非常重要。
namespace MigrationsAutomaticDemo.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class AddBlogRating : DbMigration
{
public override void Up()
{
AddColumn("Blogs", "Rating", c => c.Int(nullable: false, defaultValue: 3));
}
public override void Down()
{
DropColumn("Blogs", "Rating");
}
}
}
我们编辑的迁移一切正常,所以我们可以使用Update-Database来更新数据库。
- 在包管理器控制台中运行 Update-Database 命令。
返回自动迁移
现在,我们可以自由地为较简单的更改切换回自动迁移。 Code First Migrations 将根据它在每个基于代码的迁移的代码隐藏文件中存储的元数据,按照正确的顺序执行自动迁移和代码迁移。
- 将 Post.Abstract 属性添加到模型中
public string Abstract { get; set; }
现在,我们可以使用 Update-Database 来促使 Code First 迁移通过自动迁移将此更改推送到数据库中。
- 在包管理器控制台中运行 Update-Database 命令。
总结
在本演练中,你了解了如何使用自动迁移将模型更改推送到数据库。 还了解了如何在需要更多控制时在自动迁移之间构建基架并运行基于代码的迁移。