教程:使用迁移功能 - ASP.NET MVC 和 EF CoreTutorial: Using the migrations feature - ASP.NET MVC with EF Core

本教程使用 EF Core 迁移功能管理数据模型更改。In this tutorial, you start using the EF Core migrations feature for managing data model changes. 后续教程将在更改数据模型时添加更多迁移。In later tutorials, you'll add more migrations as you change the data model.

在本教程中,你将了解:In this tutorial, you:

  • 了解迁移相关信息Learn about migrations
  • 更改连接字符串Change the connection string
  • 创建初始迁移Create an initial migration
  • 检查 Up 和 Down 方法Examine Up and Down methods
  • 了解数据模型快照Learn about the data model snapshot
  • 应用迁移Apply the migration

系统必备Prerequisites

关于迁移About migrations

开发新应用程序时,数据模型会频繁更改。每当模型更改时,模型都无法与数据库保持同步。When you develop a new application, your data model changes frequently, and each time the model changes, it gets out of sync with the database. 本系列教程首先配置 Entity Framework 以创建数据库(如果不存在)。You started these tutorials by configuring the Entity Framework to create the database if it doesn't exist. 之后,每当更改数据模型(添加、删除或更改实体类或更改 DbContext 类)时,你都可以删除数据库,EF 将创建匹配该模型的新数据库并用测试数据为其设定种子。Then each time you change the data model -- add, remove, or change entity classes or change your DbContext class -- you can delete the database and EF creates a new one that matches the model, and seeds it with test data.

这种使数据库与数据模型保持同步的方法适用于多种情况,但将应用程序部署到生产环境的情况除外。This method of keeping the database in sync with the data model works well until you deploy the application to production. 当应用程序在生产环境中运行时,它通常会存储要保留的数据,以便不会在每次更改(如添加新列)时丢失所有数据。When the application is running in production it's usually storing data that you want to keep, and you don't want to lose everything each time you make a change such as adding a new column. EF Core 迁移功能可通过使 EF 更新数据库 架构而不是创建新数据库来解决此问题。The EF Core Migrations feature solves this problem by enabling EF to update the database schema instead of creating a new database.

要使用迁移,可使用“包管理器控制台”(PMC) 或命令行接口 (CLI)。To work with migrations, you can use the Package Manager Console (PMC) or the command-line interface (CLI). 以下教程演示如何使用 CLI 命令。These tutorials show how to use CLI commands. 有关 PMC 的信息,请转到本教程末尾Information about the PMC is at the end of this tutorial.

更改连接字符串Change the connection string

在 appsettings.json 文件中,将连接字符串中的数据库的名称更改为 ContosoUniversity2 或正在使用的计算机上未使用过的其他名称。In the appsettings.json file, change the name of the database in the connection string to ContosoUniversity2 or some other name that you haven't used on the computer you're using.

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

此更改将设置项目,以便初始迁移创建新的数据库。This change sets up the project so that the first migration will create a new database. 这并不是开始使用迁移的必要操作,但稍后你便会了解这样做的好处。This isn't required to get started with migrations, but you'll see later why it's a good idea.

备注

除更改数据库名称外,删除数据库同样可行。As an alternative to changing the database name, you can delete the database. 使用 SQL Server 对象资源管理器 (SSOX) 或 database drop CLI 命令:Use SQL Server Object Explorer (SSOX) or the database drop CLI command:

dotnet ef database drop

下面的部分说明如何运行 CLI 命令。The following section explains how to run CLI commands.

创建初始迁移Create an initial migration

保存更改并生成项目。Save your changes and build the project. 然后打开命令窗口并导航到项目文件夹。Then open a command window and navigate to the project folder. 下面是执行此操作的快速方法:Here's a quick way to do that:

  • 在解决方案资源管理器中,右键单击项目,然后从上下文菜单中选择“在文件资源管理器中打开文件夹”。In Solution Explorer, right-click the project and choose Open Folder in File Explorer from the context menu.

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

  • 在地址栏中输入“cmd”,然后按 Enter。Enter "cmd" in the address bar and press Enter.

    打开命令窗口

在命令窗口中输入以下命令:Enter the following command in the command window:

dotnet ef migrations add InitialCreate

命令窗口中出现如下输出:You see output like the following in the command window:

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" 命令的可执行文件”,请参阅此博客文章获取故障排除帮助。If you see an error message No executable found matching command "dotnet-ef", see this blog post for help troubleshooting.

如果看到错误消息“无法访问文件...ContosoUniversity.dll,因为它正被另一个进程使用。”,请在 Windows 系统托盘中找到 IIS Express 图标并右键单击,然后单击“ContosoUniversity”>“停止站点”*。If you see an error message "cannot access the file ... ContosoUniversity.dll because it is being used by another process.", find the IIS Express icon in the Windows System Tray, and right-click it, then click ContosoUniversity > Stop Site.

检查 Up 和 Down 方法Examine Up and Down methods

执行 migrations add 命令时,EF 已生成将用于从头创建数据库的代码。When you executed the migrations add command, EF generated the code that will create the database from scratch. 此代码位于“Migrations”文件夹中名为 <timestamp>_InitialCreate.cs 的文件中。This code is in the Migrations folder, in the file named <timestamp>_InitialCreate.cs. InitialCreate 类的 Up 的方法将创建与数据模型实体集相对应的数据库表,Down 方法将删除这些表,如下面的示例所示。The Up method of the InitialCreate class creates the database tables that correspond to the data model entity sets, and the Down method deletes them, as shown in the following example.

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 方法为迁移实现数据模型更改。Migrations calls the Up method to implement the data model changes for a migration. 输入用于回退更新的命令时,迁移调用 Down 方法。When you enter a command to roll back the update, Migrations calls the Down method.

此代码适用于输入 migrations add InitialCreate 命令时所创建的初始迁移。This code is for the initial migration that was created when you entered the migrations add InitialCreate command. 迁移名称参数(本示例中为“InitialCreate”)用于指定文件名,并且你可以按需使用任何名称。The migration name parameter ("InitialCreate" in the example) is used for the file name and can be whatever you want. 最好选择能概括迁移中所执行操作的字词或短语。It's best to choose a word or phrase that summarizes what is being done in the migration. 例如,可将后面的迁移命名为“AddDepartmentTable”。For example, you might name a later migration "AddDepartmentTable".

如果创建初始迁移时已存在数据库,则会生成数据库创建代码,但此代码不必运行,因为数据库已与数据库模型相匹配。If you created the initial migration when the database already exists, the database creation code is generated but it doesn't have to run because the database already matches the data model. 将应用部署到其中尚不存在数据库的其他环境时,此代码将运行以创建数据库,因此最好提前进行测试。When you deploy the app to another environment where the database doesn't exist yet, this code will run to create your database, so it's a good idea to test it first. 这也是提前更改连接字符串中数据库的名称的原因,这样迁移才能从头创建新数据库。That's why you changed the name of the database in the connection string earlier -- so that migrations can create a new one from scratch.

数据模型快照The data model snapshot

迁移在 Migrations/SchoolContextModelSnapshot.cs 中创建当前数据库架构的快照。Migrations creates a snapshot of the current database schema in Migrations/SchoolContextModelSnapshot.cs. 添加迁移时,EF 会通过将数据模型与快照文件进行对比来确定已更改的内容。When you add a migration, EF determines what changed by comparing the data model to the snapshot file.

删除迁移时,请使用 dotnet ef migrations remove 命令。When deleting a migration, use the dotnet ef migrations remove command. dotnet ef migrations remove 删除迁移,并确保正确重置快照。dotnet ef migrations remove deletes the migration and ensures the snapshot is correctly reset.

有关如何使用快照文件的详细信息,请参阅团队环境中的 EF Core 迁移See EF Core Migrations in Team Environments for more information about how the snapshot file is used.

应用迁移Apply the migration

在命令窗口中,输入以下命令以创建数据库并在其中创建表。In the command window, enter the following command to create the database and tables in it.

dotnet ef database update

该命令的输出与 migrations add 命令的输出相似,但其中还包含设置该数据库的 SQL 命令的日志。The output from the command is similar to the migrations add command, except that you see logs for the SQL commands that set up the database. 下面的示例输出中省略了大部分日志。Most of the logs are omitted in the following sample output. 如果希望日志消息中不使用此详细级别,则可更改 appsettings.Development.json 文件中的日志级别。If you prefer not to see this level of detail in log messages, you can change the log level in the appsettings.Development.json file. 有关更多信息,请参见ASP.NET Core 中的日志记录For more information, see 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 对象资源管理器检查数据库(与第一个教程中的做法相同)。Use SQL Server Object Explorer to inspect the database as you did in the first tutorial. 你会发现添加了 __EFMigrationsHistory 表,该表可用于跟踪已应用到数据库的迁移。You'll notice the addition of an __EFMigrationsHistory table that keeps track of which migrations have been applied to the database. 查看该表中的数据,其中显示对应初始迁移的一行数据。View the data in that table and you'll see one row for the first migration. (上面的 CLI 输出示例中最后部分的日志显示了创建此行的 INSERT 语句。)(The last log in the preceding CLI output example shows the INSERT statement that creates this row.)

运行应用程序以验证所有内容照旧运行。Run the application to verify that everything still works the same as before.

“学生索引”页

比较 CLI 和 PMCCompare CLI and PMC

可通过 .NET Core CLI 命令或 Visual Studio 包管理器控制台 (PMC) 窗口中的 PowerShell cmdlet 使用可管理迁移的 EF 工具。The EF tooling for managing migrations is available from .NET Core CLI commands or from PowerShell cmdlets in the Visual Studio Package Manager Console (PMC) window. 本教程演示如何使用 CLI,但也可以根据喜好使用 PMC。This tutorial shows how to use the CLI, but you can use the PMC if you prefer.

适用于 PMC 命令的 EF 命令位于 Microsoft.EntityFrameworkCore.Tools 程序包中。The EF commands for the PMC commands are in the Microsoft.EntityFrameworkCore.Tools package. 此包包含在 Microsoft.AspNetCore.App 元包中,因此,如果应用具有对 Microsoft.AspNetCore.App 的包引用,则无需添加包引用。This package is included in the Microsoft.AspNetCore.App metapackage, so you don't need to add a package reference if your app has a package reference for Microsoft.AspNetCore.App.

重要提示: 此包与通过编辑 .csproj 文件为 CLI 安装的包不同。Important: This isn't the same package as the one you install for the CLI by editing the .csproj file. 此程序包的名称以 Tools 结尾,而 CLI 程序包的名称以 Tools.DotNet 结尾。The name of this one ends in Tools, unlike the CLI package name which ends in Tools.DotNet.

有关 CLI 命令的详细信息,请参阅 .NET Core CLIFor more information about the CLI commands, see .NET Core CLI.

有关 PMC 命令的详细信息,请参阅包管理器控制台 (Visual Studio)For more information about the PMC commands, see Package Manager Console (Visual Studio).

获取代码Get the code

下载或查看已完成的应用程序。Download or view the completed application.

下一步Next step

在本教程中,你将了解:In this tutorial, you:

  • 已了解迁移相关信息Learned about migrations
  • 已了解 NuGet 迁移包Learned about NuGet migration packages
  • 已更改连接字符串Changed the connection string
  • 已创建初始迁移Created an initial migration
  • 已检查 Up 和 Down 方法Examined Up and Down methods
  • 已了解数据模型快照Learned about the data model snapshot
  • 已应用迁移Applied the migration

请继续阅读下一篇教程,开始了解有关展开数据模型的更高级主题。Advance to the next tutorial to begin looking at more advanced topics about expanding the data model. 同时还将介绍创建并应用其他迁移的方法。Along the way you'll create and apply additional migrations.