【EF Core】迁移与反向工程
简介
EF Core 提供两种方法来保持 EF Core 模型和数据库架构同步。至于我们应该选用哪个方法,请确定你是希望以 EF Core 模型为准还是以数据库为准。
迁移
如果希望以 EF Core 模型为准,请使用迁移。
在实际项目中,数据模型随着功能的实现而变化:添加和删除新的实体或属性,并且需要相应地更改数据库架构,使其与应用程序保持同步。 EF Core 中的迁移功能能够以递增方式更新数据库架构,使其与应用程序的数据模型保持同步,同时保留数据库中的现有数据。
当数据模型更改时,开发人员使用 EF Core 工具添加相应的迁移。EF Core 将当前模型与旧模型的快照进行比较,以确定差异,并生成迁移源文件。
生成新的迁移后,可通过多种方式将其应用于数据库。 EF Core 在一个历史记录表中记录所有应用的迁移,使其知道哪些迁移已应用,哪些迁移尚未应用。
反向工程
如果希望以数据库架构为准,请使用反向工程。
可通过将数据库架构反向工程到 EF Core 模型来生成相应的 DbContext 和实体类型。
创建和应用迁移的两种方式
dotnet cli工具
可用于windows、linux、macOS。这些命令以dotnet ef
开头
安装dotnet core cli工具:
dotnet tool install --global dotnet-ef
包管理控制台工具
只能在VisualStudio中运行,以动词开头,例如:Add-Migration
、Update-Database
需要安装Nuget包:
Install-Package Microsoft.EntityFrameworkCore.Tools
Microsoft.EntityFrameworkCore.Tools
包中包含Microsoft.EntityFrameworkCore.Design
如果迁移文件在单独的项目中,迁移项目和主项目中都要安装包Microsoft.EntityFrameworkCore.Tools
,主项目中也可以安装包Microsoft.EntityFrameworkCore.Design
Migrations目录
创建迁移后,会生成Migrations目录,里面包含以下文件:
- XXXXXXXXXXXXXX_AddCreatedTimestamp-主迁移文件。 包含应用迁移所需的操作(在 Up 中)和还原迁移所需的操作(在 Down 中)。
- MyContextModelSnapshot.cs--当前模型的快照。 用于确定添加下一迁移时的更改内容。
文件名中的时间戳有助于保证文件按时间顺序排列,以便你查看更改情况。
迁移流程
安装Nuget包
Install-Package Microsoft.EntityFrameworkCore.Tools
创建迁移文件
cli:dotnet ef migrations add InitialCreate
vs:Add-Migration InitialCreate
InitialCreate是迁移的描述名称
EF Core将在项目中创建名为“Migrations”的目录并生成一些文件
应用迁移
添加迁移后,需要对其进行部署并将其应用于数据库。 有多种策略可用于执行此操作,生产环境和开发环境使用不同的策略。
cli:dotnet ef database update
vs:Update-Database
这种应用迁移的方法非常适合本地开发,但不太适用于生产环境。生产环境使用sql部署
其他迁移操作
删除迁移
有时,你可能在添加迁移后意识到需要在应用迁移前对 EF Core 模型作出其他更改。 要删除上个迁移,删除迁移后可对模型作出其他更改,然后再次添加迁移。请使用如下命令:
cli:dotnet ef migrations remove
vs:Remove-Migration
避免删除已应用到生产数据库的任何迁移。 这样做意味着你将无法从数据库还原这些迁移,并且可能会破坏后续迁移所做的假设。
列出所有迁移
cli:dotnet ef migrations list
vs:Get-Migration
回滚
上面创建迁移后执行Update-Database
,可以将迁移应用到数据库。
Update-Database
后面加参数表示回滚到指定迁移文件,如Update-Database InitialCreate
,表示数据库回滚到InitialCreate
这个迁移,脚本不会有变化
生成迁移脚本(Script-Migration
)
上面说的应用迁移Update-Database
,只适用于开发环境,线上环境应该生成迁移脚本,并手动执行
Script-Migration
命令用来生成SQL脚本,并不执行,需要手动执行
Script-Migration
可以生成D版本到F版本之间的SQL脚本
Script-Migration D F
生成D版本到最新版本的SQL脚本:
Script-Migration D
重置所有迁移
在某些极端情况下,可能需要删除所有迁移并重新开始。 这可以通过删除 迁移 文件夹并删除数据库来轻松完成;此时,你可以创建新的初始迁移,其中将包含整个当前架构。
还可以重置所有迁移并创建单个迁移,而不会丢失数据。 这有时称为 "squashing",包括一些手动工作:
- 删除 Migrations 文件夹
- 创建新迁移并为其生成 SQL 脚本
- 在数据库中,删除迁移历史记录表中的所有行
- 将单个行插入到迁移历史记录中,记录已应用的第一个迁移,因为表已经存在。 insert SQL 是上面生成的 SQL 脚本中的最后一个操作。
自定义迁移文件
尽管 EF Core 通常会创建准确的迁移,但应始终查看代码,并确保其对应于所需的更改;
列重命名
在重命名属性时需要自定义迁移。 例如,如果将属性重命名 Name 为 FullName ,EF Core 将生成以下迁移:
migrationBuilder.DropColumn(
name: "Name",
table: "Customers");
migrationBuilder.AddColumn(
name: "FullName",
table: "Customers",
nullable: true);
如果以上迁移按原样应用,则所有客户名称都将丢失。 若要重命名列,请将上面生成的迁移替换为以下内容:
migrationBuilder.RenameColumn(
name: "Name",
table: "Customers",
newName: "FullName");
当某个操作可能会导致数据丢失(例如删除某列),搭建迁移基架过程将对此发出警告。 如果看到此警告,务必检查迁移代码的准确性。
添加原始SQL
重命名列可以通过内置 API 来实现,在许多情况下,这是不可能的。 例如,我们可能希望将现有的 FirstName 和属性替换为 LastName 一个新的 FullName 属性。 EF Core 生成的迁移如下:
migrationBuilder.DropColumn(
name: "FirstName",
table: "Customer");
migrationBuilder.DropColumn(
name: "LastName",
table: "Customer");
migrationBuilder.AddColumn(
name: "FullName",
table: "Customer",
nullable: true);
这会导致不需要的数据丢失。 为了传输旧列中的数据,我们会重新排列迁移并引入原始 SQL 操作,如下所示:
migrationBuilder.AddColumn(
name: "FullName",
table: "Customer",
nullable: true);
migrationBuilder.Sql(
@"
UPDATE Customer
SET FullName = FirstName + ' ' + LastName;
");
migrationBuilder.DropColumn(
name: "FirstName",
table: "Customer");
migrationBuilder.DropColumn(
name: "LastName",
table: "Customer");