迁移

教程:使用迁移功能 - ASP.NET MVC 和 EF Core

本教程使用 EF Core 迁移功能管理数据模型更改。 后续教程将在更改数据模型时添加更多迁移。

在本教程中,你将了解:

  • 了解迁移相关信息
  • 更改连接字符串
  • 创建初始迁移
  • 检查 Up 和 Down 方法
  • 了解数据模型快照
  • 应用迁移

先决条件

关于迁移

开发新应用程序时,数据模型会频繁更改。每当模型更改时,模型都无法与数据库保持同步。 本系列教程首先配置 Entity Framework 以创建数据库(如果不存在)。 之后,每当更改数据模型(添加、删除或更改实体类或更改 DbContext 类)时,你都可以删除数据库,EF 将创建匹配该模型的新数据库并用测试数据为其设定种子。

这种使数据库与数据模型保持同步的方法适用于多种情况,但将应用程序部署到生产环境的情况除外。 当应用程序在生产环境中运行时,它通常会存储要保留的数据,以便不会在每次更改(如添加新列)时丢失所有数据。 EF Core 迁移功能可通过使 EF 更新数据库 架构而不是创建新数据库来解决此问题。

要使用迁移,可使用“包管理器控制台”(PMC) 或 CLI 。 以下教程演示如何使用 CLI 命令。 有关 PMC 的信息,请转到本教程末尾

更改连接字符串

在 appsettings.json 文件中,将连接字符串中的数据库的名称更改为 ContosoUniversity2 或正在使用的计算机上未使用过的其他名称。

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity2;Trusted_Connection=True;MultipleActiveResultSets=true"
  },

此更改将设置项目,以便初始迁移创建新的数据库。 这并不是开始使用迁移的必要操作,但稍后你便会了解这样做的好处。

备注

除更改数据库名称外,删除数据库同样可行。 使用 SQL Server 对象资源管理器 (SSOX) 或 database drop CLI 命令:

dotnet ef database drop

下面的部分说明如何运行 CLI 命令。

创建初始迁移

保存更改并生成项目。 然后打开命令窗口并导航到项目文件夹。 下面是执行此操作的快速方法:

  • 在解决方案资源管理器中,右键单击项目,然后从上下文菜单中选择“在文件资源管理器中打开文件夹”。

    “在文件资源管理器中打开”菜单项

  • 在地址栏中输入“cmd”,然后按 Enter。

    打开命令窗口

在命令窗口中输入以下命令:

dotnet ef migrations add InitialCreate

命令窗口中出现如下输出:

info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core 2.2.0-rtm-35687 initialized 'SchoolContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
Done. To undo this action, use 'ef migrations remove'

备注

如果出现错误消息“找不到任何匹配 "dotnet-ef" 命令的可执行文件”,请参阅此博客文章获取故障排除帮助。

如果看到错误消息“无法访问文件...ContosoUniversity.dll,因为它正被另一个进程使用。”,请在 Windows 系统托盘中找到 IIS Express 图标并右键单击,然后单击“ContosoUniversity”>“停止站点”。

检查 Up 和 Down 方法

执行 migrations add 命令时,EF 已生成将用于从头创建数据库的代码。 此代码位于“Migrations”文件夹中名为 <timestamp>_InitialCreate.cs 的文件中。 InitialCreate 类的 Up 的方法将创建与数据模型实体集相对应的数据库表,Down 方法将删除这些表,如下面的示例所示。

public partial class InitialCreate : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Course",
            columns: table => new
            {
                CourseID = table.Column<int>(nullable: false),
                Credits = table.Column<int>(nullable: false),
                Title = table.Column<string>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Course", x => x.CourseID);
            });

        // Additional code not shown
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "Enrollment");
        // Additional code not shown
    }
}

迁移调用 Up 方法为迁移实现数据模型更改。 输入用于回退更新的命令时,迁移调用 Down 方法。

此代码适用于输入 migrations add InitialCreate 命令时所创建的初始迁移。 迁移名称参数(本示例中为“InitialCreate”)用于指定文件名,并且你可以按需使用任何名称。 最好选择能概括迁移中所执行操作的字词或短语。 例如,可将后面的迁移命名为“AddDepartmentTable”。

如果创建初始迁移时已存在数据库,则会生成数据库创建代码,但此代码不必运行,因为数据库已与数据库模型相匹配。 将应用部署到其中尚不存在数据库的其他环境时,此代码将运行以创建数据库,因此最好提前进行测试。 这也是提前更改连接字符串中数据库的名称的原因,这样迁移才能从头创建新数据库。

数据模型快照

迁移在 Migrations/SchoolContextModelSnapshot.cs 中创建当前数据库架构的快照。 添加迁移时,EF 会通过将数据模型与快照文件进行对比来确定已更改的内容。

使用 dotnet ef migrations remove 命令删除迁移。 dotnet ef migrations remove 删除迁移,并确保正确重置快照。 如果 dotnet ef migrations remove 失败,使用 dotnet ef migrations remove -v 获取失败的详细信息。

有关如何使用快照文件的详细信息,请参阅团队环境中的 EF Core 迁移

应用迁移

在命令窗口中,输入以下命令以创建数据库并在其中创建表。

dotnet ef database update

该命令的输出与 migrations add 命令的输出相似,但其中还包含设置该数据库的 SQL 命令的日志。 下面的示例输出中省略了大部分日志。 如果希望日志消息中不使用此详细级别,则可更改 appsettings.Development.json 文件中的日志级别。 有关详细信息,请参阅 .NET Core 和 ASP.NET Core 中的日志记录

info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core 2.2.0-rtm-35687 initialized 'SchoolContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (274ms) [Parameters=[], CommandType='Text', CommandTimeout='60']
      CREATE DATABASE [ContosoUniversity2];
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (60ms) [Parameters=[], CommandType='Text', CommandTimeout='60']
      IF SERVERPROPERTY('EngineEdition') <> 5
      BEGIN
          ALTER DATABASE [ContosoUniversity2] SET READ_COMMITTED_SNAPSHOT ON;
      END;
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (15ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      CREATE TABLE [__EFMigrationsHistory] (
          [MigrationId] nvarchar(150) NOT NULL,
          [ProductVersion] nvarchar(32) NOT NULL,
          CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId])
      );

<logs omitted for brevity>

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
      VALUES (N'20190327172701_InitialCreate', N'2.2.0-rtm-35687');
Done.

使用 SQL Server 对象资源管理器检查数据库(与第一个教程中的做法相同)。 你会发现添加了 __EFMigrationsHistory 表,该表可用于跟踪已应用到数据库的迁移。 查看该表中的数据,其中显示对应初始迁移的一行数据。 (上面的 CLI 输出示例中最后部分的日志显示了创建此行的 INSERT 语句。)

运行应用程序以验证所有内容照旧运行。

“学生索引”页

比较 CLI 和 PMC

可通过 .NET Core CLI 命令或 Visual Studio 包管理器控制台 (PMC) 窗口中的 PowerShell cmdlet 使用可管理迁移的 EF 工具。 本教程演示如何使用 CLI,但也可以根据喜好使用 PMC。

适用于 PMC 命令的 EF 命令位于 Microsoft.EntityFrameworkCore.Tools 程序包中。 此包包含在 Microsoft.AspNetCore.App 元包中,因此,如果应用具有对 Microsoft.AspNetCore.App 的包引用,则无需添加包引用。

重要提示: 此包与通过编辑 .csproj 文件为 CLI 安装的包不同。 此程序包的名称以 Tools 结尾,而 CLI 程序包的名称以 Tools.DotNet 结尾。

有关 CLI 命令的详细信息,请参阅 .NET Core CLI

有关 PMC 命令的详细信息,请参阅包管理器控制台 (Visual Studio)

获取代码

下载或查看已完成的应用程序。

下一步

在本教程中,你将了解:

  • 已了解迁移相关信息
  • 已了解 NuGet 迁移包
  • 已更改连接字符串
  • 已创建初始迁移
  • 已检查 Up 和 Down 方法
  • 已了解数据模型快照
  • 已应用迁移

请继续阅读下一篇教程,开始了解有关展开数据模型的更高级主题。 同时还将介绍创建并应用其他迁移的方法。