ASP.NET Core 中的 Razor 页面和 EF Core - 迁移
Contoso University Web 应用演示了如何使用 EF Core 和 Visual Studio 创建 Razor 页面 Web 应用。若要了解系列教程,请参阅第一个教程。
本教程使用 EF Core 迁移功能管理数据模型更改。
如果遇到无法解决的问题,请下载已完成应用。
开发新应用时,数据模型会频繁更改。 每当模型发生更改时,都无法与数据库进行同步。 本教程首先配置 Entity Framework 以创建数据库(如果不存在)。 每当数据模型发生更改时:
- DB 都会被删除。
- EF 都会创建一个新数据库来匹配该模型。
- 应用使用测试数据为 DB 设定种子。
这种使 DB 与数据模型保持同步的方法适用于多种情况,但将应用部署到生产环境的情况除外。 当应用在生产环境中运行时,应用通常会存储需要保留的数据。 每当发生更改(例如添加新列)时,应用都无法在具有测试 DB 的环境下启动。 EF Core 迁移功能可通过使 EF Core 更新 DB 架构而不是创建新 DB 来解决此问题。
数据模型发生更改时,迁移将更新架构并保留现有数据,而无需删除或重新创建 DB。
删除数据库
使用 SQL Server 对象资源管理器 (SSOX) 或 database drop 命令:
在“包管理器控制台”(PMC) 中运行以下命令:
Drop-Database
从 PMC 运行 Get-Help about_EntityFrameworkCore
,获取帮助信息。
创建初始迁移并更新 DB
生成项目并创建第一个迁移。
Add-Migration InitialCreate
Update-Database
了解 Up 和 Down 方法
EF Core migrations add 命令已生成用于创建 DB 的代码。 此迁移代码位于 Migrations<timestamp>_InitialCreate.cs 文件中。 InitialCreate 类的 Up 的方法创建与数据模型实体集相对应的 DB 表。 Down 方法删除这些表,如下例所示:
C#
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Course",
columns: table => new
{
CourseID = table.Column<int>(nullable: false),
Title = table.Column<string>(nullable: true),
Credits = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Course", x => x.CourseID);
});
migrationBuilder.CreateTable(
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Enrollment");
migrationBuilder.DropTable(
name: "Course");
migrationBuilder.DropTable(
name: "Student");
}
}
迁移调用 Up 方法为迁移实现数据模型更改。 输入用于回退更新的命令时,迁移调用 Down 方法。
前面的代码适用于初始迁移。 该代码是运行 migrations add InitialCreate 命令时创建的。 迁移名称参数(本示例中为“InitialCreate”)用于指定文件名。 迁移名称可以是任何有效的文件名。 最好选择能概括迁移中所执行操作的字词或短语。 例如,添加了系表的迁移可称为“AddDepartmentTable”。
如果创建了初始迁移并且存在 DB:
- 会生成 DB 创建代码。
- DB 创建代码不需要运行,因为 DB 已与数据模型相匹配。 即使 DB 创建代码运行也不会做出任何更改,因为 DB 已与数据模型相匹配。
如果将应用部署到新环境,则必须运行 DB 创建代码才能创建 DB。
先前删除了 DB,因此已不存在,所以迁移会创建新的 DB。
数据模型快照
迁移在 Migrations/SchoolContextModelSnapshot.cs 中创建当前数据库架构的快照。 添加迁移时,EF 会通过将数据模型与快照文件进行对比来确定已更改的内容。
若要删除迁移,请使用以下命令:
Remove-Migration
删除迁移命令会删除迁移并确保正确重置快照。
删除 EnsureCreated 并测试应用
早期开发使用了 EnsureCreated。 本教程将使用迁移。 EnsureCreated 具有以下限制:
- 绕过迁移并创建 DB 和架构。
- 不会创建迁移表。
- 不能与迁移一起使用。
- 专门用于在频繁删除并重新创建 DB 的情况下进行测试或快速制作原型。
删除 EnsureCreated:
C#
context.Database.EnsureCreated();
运行应用并验证 DB 设定为种子。
检查数据库
使用 SQL Server 对象资源管理器检查 DB。 请注意,增加了 __EFMigrationsHistory 表。 __EFMigrationsHistory 表跟踪已应用到 DB 的迁移。 查看 __EFMigrationsHistory 表中的数据,其中显示对应初始迁移的一行数据。 上面的 CLI 输出示例中最后部分的日志显示了创建此行的 INSERT 语句。
运行应用并验证一切正常运行。
在生产环境中应用迁移
不建议生产应用在应用程序启动时调用 Database.Migrate。 不应从服务器场中的应用调用 Migrate。 例如,已将应用在云中部署为横向扩展(运行应用的多个示例)的情况。
应在部署过程中以受控的方式执行数据库迁移。 生产数据库迁移方法包括:
- 使用迁移创建 SQL 脚本,并在部署过程中使用 SQL 脚本。
- 在受控的环境中运行 dotnet ef database update。
EF Core 使用 __MigrationsHistory 表查看是否需要运行任何迁移。 如果 DB 已是最新,则无需运行迁移。
疑难解答
下载已完成应用。
应用会生成以下异常:
text
SqlException: Cannot open database "ContosoUniversity" requested by the login.
The login failed.
Login failed for user 'user name'.
解决方案:运行 dotnet ef database update