【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-MigrationUpdate-Database
需要安装Nuget包:

Install-Package Microsoft.EntityFrameworkCore.Tools

NuGet包

单个项目

如果迁移文件在启动项目中,在启动项目安装NuGet包:

Install-Package Microsoft.EntityFrameworkCore.SqlServer
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脚本或自动迁移
使用代码自动迁移:

dbContext.Database.Migrate();

其他迁移操作

删除迁移

有时,你可能在添加迁移后意识到需要在应用迁移前对 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<string>(
    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<string>(
    name: "FullName",
    table: "Customer",
    nullable: true);

这会导致不需要的数据丢失。 为了传输旧列中的数据,我们会重新排列迁移并引入原始 SQL 操作,如下所示:

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");

反向工程

根据数据库表来反向生成实体类、上下文
Scaffold-DbContext '连接字符串' 指定数据库的EF包名
sqlserver:

Scaffold-DbContext 'Data Source=.;Initial Catalog=EFCoreDB;User ID=sa;Password=123456' Microsoft.EntityFrameworkCore.SqlServer

Scaffold-DbContext命令详细

【Scaffold-DbContext "Server=localhost;Database=EFDB01;User ID=sa;Password=123456;" Microsoft.EntityFrameworkCore.SqlServer -ContextDir DbContext -OutputDir Models -UseDatabaseNames -Context EFDB01Context】
  • -ContextDir DbContext : 代表EF上下文类放在DbContex文件夹的目录下
  • -OutputDir Models:代表所有的实体类放在Models文件夹的目录下
  • -UseDatabaseNames:代表完全按照数据库中表名或字段来映射生成相应的实体
  • -Context EFDB01Context:代表指定EF上下文的名称为“EFDB01Context”,默认的生成规则是: 数据库名+Context
  • -DataAnnotations: 代表用数据注解的形式配置实体类属性,默认用的是FluentApi的形式进行配置。
  • -Tables SysOperLogInfor,SysUserInfor:表示仅映射SysOperLogInfor,SysUserInfor两张表。

覆盖

如果数据变动很小,那么我们完全可以手动的去改一下代码的配置即可。
如果数据库修改内容多,手动修改代码配置会很麻烦,这个时候我们使用指令 【-Force】再次映射,即覆盖了原先的代码配置映射。
覆盖的完整版的指令:

【Scaffold-DbContext "Server=localhost;Database=MagicDB;User ID=sa;Password=123456;" Microsoft.EntityFrameworkCore.SqlServer -ContextDir DbContext -OutputDir Models -UseDatabaseNames -Context MagicDBContext -DataAnnotations -Tables SysOperLogInfor,SysUserInfor -Force】
posted @ 2022-04-14 21:49  .Neterr  阅读(1167)  评论(0编辑  收藏  举报