使用Entity Framework Core管理数据库架构进行数据迁移
Posted JimCarter
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Entity Framework Core管理数据库架构进行数据迁移相关的知识,希望对你有一定的参考价值。
文章目录
在实际项目中,数据模型随着功能的实现而变化:添加和删除新的实体或属性,并且需要相应地更改数据库架构,使其与应用程序保持同步。 EF Core 中的迁移功能能够以递增方式更新数据库架构,使其与应用程序的数据模型保持同步,同时保留数据库中的现有数据。
简要地说,迁移的方式如下:
- 当引入数据模型更改时,开发人员使用 EF Core 工具添加相应的迁移,以描述使数据库架构保持同步所需的更新。EF Core 将当前模型与旧模型的快照进行比较,以确定差异,并生成迁移源文件;文件可在项目的源代码管理中进行跟踪,如任何其他源文件。
- 生成新的迁移后,可通过多种方式将其应用于数据库。 EF Core 在一个特殊的历史记录表中记录所有应用的迁移,使其知道哪些迁移已应用,哪些迁移尚未应用。
迁移简单来说有两种方式:
- 粗暴方式:就是直接删库,多用于项目初始阶段。先调用
Database.EnsureDeleted();
,然后调用Database.EnsureCreated();
。优点就是快,不啰嗦。缺点就是之前的数据全没了。 - 优雅方式:既可以更新表结构又可以保留数据库原有的数据。优雅迁移的过程就是先创建迁移记录,然后执行这个迁移记录来更新数据库。我们接下来会重点介绍这种方式。
1. 进行迁移
1.1 常用命令
首先熟悉几个常用的PMC迁移命令。
PMC命令 | 控制台命令 | 作用 |
---|---|---|
get-help about_entityframework | 提供EFCore的帮助信息,如果需要查看Add-Migration命令的具体信息,可以执行get-help Add-Migration | |
Add-Migration | dotnet ef migrations add XXXXX | 创建迁移记录 |
Update-Database | dotnet ef database update | 执行迁移记录 |
Remove-Migration | dotnet ef migrations remove | 删除迁移 |
Get-Migration | dotnet ef migrations list | 列出迁移 |
当然如果你更熟悉使用控制台,则可以安装控制台的ef迁移工具,参考。
1.2 迁移过程
-
首先,安装nuget包Microsoft.EntityFrameworkCore.Tools和Microsoft.EntityFrameworkCore.Design(包含了需要的迁移命令)。
-
然后,打开包管理器控制台,路径如下:
打开之后就看到了命令窗口。 -
创建迁移记录,执行
Add-Migration RecordXXXX
命令(其中RecordXXX是迁移记录的名称,自己可以随便写),就可以看到资源管理器里多了一个Migrations
文件夹,里面包含一些文件,这个文件夹的作用后续会介绍。
-
执行迁移记录:
Update-Database
用来执行迁移记录,执行完之后数据库接口就会变更。除了这个执行这个命令进行数据库变更外,还可以通过导出脚本的方式进行变更,后续会介绍。
-
此时就可以看到数据库已经响应了变更。而且数据库里多了一个表:
1.3 Migrations
文件夹的作用
目录下有以下三个文件:
- 20210812083634_MigraRecordAAA.cs:主迁移文件。 包含应用迁移所需的操作(在 Up 方法中)和还原迁移所需的操作(在 Down方法 中)。
- 20210812083634_MigraRecordAAA.Designer.cs:迁移元数据文件。 包含 EF 所用的信息。
- OpsDbContextModelSnapshot.cs:当前模型的快照。 用于确定添加下一迁移时的更改内容。
文件名中的时间戳有助于保证文件按时间顺序排列,以便你查看更改情况。
如果你不想把迁移记录放到默认的Migrations
目录里,则创建迁移记录时,可以指定目录:Add-Migration MigrationBBBB -OutputDir AAA\\BBBB
。
1.4 自定义Migrations
里的迁移代码
保险起见在执行迁移记录之前你应该浏览一遍生成的迁移代码,确保不会有问题。
1.4.1 列重命名
在重命名属性的时候,会导致列重命名。此项操作需要特别注意。如果将属性Name
改为FullName
,EF Core将默认会生成以下迁移操作:
migrationBuilder.DropColumn(
name: "Name",
table: "Customers");
migrationBuilder.AddColumn<string>(
name: "FullName",
table: "Customers",
nullable: true);
即删除了原有的列,然后又新增一列,这样会导致原有数据的丢失。所以应做如下调整:
migrationBuilder.RenameColumn(
name: "Name",
table: "Customers",
newName: "FullName");
1.4.2 添加原始SQL
考虑这么一种情况:我们想把FirstName
和LastName
属性合并到一个新增的FullName
上。EF Core就会这么生成语句:
migrationBuilder.DropColumn(
name: "FirstName",
table: "Customer");
migrationBuilder.DropColumn(
name: "LastName",
table: "Customer");
migrationBuilder.AddColumn<string>(
name: "FullName",
table: "Customer",
nullable: true);
这么一来也会导致数据丢失,所以需要手动编辑下这个文件,执行一段预操作:
migrationBuilder.AddColumn<string>(
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");
注意:通常情况下如果执行迁移会导致数据丢失时,迁移工具会进行提醒,千万注意这个提醒。
2. 执行迁移
之前迁移除了上面我们说的Update-Database
命令之外还可以生成迁移SQL脚本,然后将脚本交给DBA执行。
常见命令:
命令 | 功能 |
---|---|
Script-Migration | 生成一个从空白数据库到最新迁移的 SQL 脚本 |
Script-Migration AddNewTables | 生成一个从记录AddNewTables到最新的SQL脚本 |
Script-Migration RecordA RecordB | 生成一个从RecordA到RecordB的脚本,如果RecordA和RecordB顺序互换,则表示回滚 |
Script-Migration -Idempotent | 生成幂等迁移脚本 |
除此之外还可以通过手写代码的方式执行迁移:
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
db.Database.Migrate();
}
host.Run();
}
参考:
https://docs.microsoft.com/zh-cn/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli
以上是关于使用Entity Framework Core管理数据库架构进行数据迁移的主要内容,如果未能解决你的问题,请参考以下文章
使用Entity Framework Core管理数据库架构进行数据迁移
使用 Key Vault 和包管理器控制台为 Entity Framework Core 连接和数据库迁移
使用 Entity Framework Core 更新相关数据
使用 ASP.NET Core 和 Entity Framework Core 进行集成测试 - 如何在每次测试时恢复数据库中的测试数据?