Entity Framework Core——5.管理数据库架构、进行数据迁移

在实际项目中,数据模型随着功能的实现而变化:添加和删除新的实体或属性,并且需要相应地更改数据库架构,使其与应用程序保持同步。 EF Core 中的迁移功能能够以递增方式更新数据库架构,使其与应用程序的数据模型保持同步,同时保留数据库中的现有数据。

简要地说,迁移的方式如下:

  • 当引入数据模型更改时,开发人员使用 EF Core 工具添加相应的迁移,以描述使数据库架构保持同步所需的更新。EF Core 将当前模型与旧模型的快照进行比较,以确定差异,并生成迁移源文件;文件可在项目的源代码管理中进行跟踪,如任何其他源文件。
  • 生成新的迁移后,可通过多种方式将其应用于数据库。 EF Core 在一个特殊的历史记录表中记录所有应用的迁移,使其知道哪些迁移已应用,哪些迁移尚未应用。

迁移简单来说有两种方式:

  1. 粗暴方式:就是直接删库,多用于项目初始阶段。先调用Database.EnsureDeleted();,然后调用Database.EnsureCreated();。优点就是快,不啰嗦。缺点就是之前的数据全没了。
  2. 优雅方式:既可以更新表结构又可以保留数据库原有的数据。优雅迁移的过程就是先创建迁移记录,然后执行这个迁移记录来更新数据库。我们接下来会重点介绍这种方式。

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 迁移过程

  1. 首先,安装nuget包Microsoft.EntityFrameworkCore.ToolsMicrosoft.EntityFrameworkCore.Design(包含了需要的迁移命令)。

  2. 然后,打开包管理器控制台,路径如下:
    在这里插入图片描述
    打开之后就看到了命令窗口。

  3. 创建迁移记录,执行Add-Migration RecordXXXX命令(其中RecordXXX是迁移记录的名称,自己可以随便写),就可以看到资源管理器里多了一个Migrations文件夹,里面包含一些文件,这个文件夹的作用后续会介绍。
    在这里插入图片描述

  4. 执行迁移记录:
    Update-Database用来执行迁移记录,执行完之后数据库接口就会变更。除了这个执行这个命令进行数据库变更外,还可以通过导出脚本的方式进行变更,后续会介绍。
    在这里插入图片描述

  5. 此时就可以看到数据库已经响应了变更。而且数据库里多了一个表:在这里插入图片描述


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

考虑这么一种情况:我们想把FirstNameLastName属性合并到一个新增的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

猜你喜欢

转载自blog.csdn.net/catshitone/article/details/119648682
今日推荐