# 数据库迁移指南 本项目使用 Entity Framework Core 迁移。迁移文件生成在: `AML_Backend/src/iCON.Abp.FX.EntityFrameworkCore.DbMigrations/Migrations/` 对应的 DbContext 为 `FXMigrationsDbContext`,设计时工厂为 `EntityFrameworkCore/FXMigrationsDbContextFactory.cs`。 生成迁移有两条等价路径:**A. Visual Studio 包管理器控制台(Windows)** 与 **B. `dotnet ef` 命令行(macOS / Linux / 无 VS 的开发环境)**。二者产物完全一致, 按你的操作系统任选其一即可。 > 说明:迁移**只在开发/构建环境生成**(生成 `*.cs` + 更新 `ModelSnapshot`); > 运行时由 `Database.Migrate()` 自动应用到数据库。**不要**用手写 `ALTER TABLE` > 代替生成迁移——运行时会读取迁移里的 `TargetModel`(完整模型快照)做比对, > 缺少对应迁移会导致模型不一致。手动改库仅可作为本地临时应急。 --- ## 路径 A · Visual Studio 包管理器控制台(Windows) ### 前置条件 - Visual Studio 开发环境 - 确保解决方案已成功构建 - 已安装 EF Core 工具 ### 步骤 1. 将 `EntityFrameworkCore.DbMigrations` 设为启动项目 2. 打开包管理器控制台(Package Manager Console) 3. 默认项目选择:`src\iCON.Abp.FX.EntityFrameworkCore.DbMigrations` 4. 执行:`Add-Migration ` 5. 迁移会在下次运行时自动应用 - 撤销上一个(尚未应用的)迁移:`Remove-Migration` --- ## 路径 B · `dotnet ef` 命令行(macOS / Linux / 无 VS) `Add-Migration`(PMC)与 `dotnet ef migrations add`(CLI)是同一功能的两种入口。 在没有 Visual Studio 的开发机(如本机 macOS)上,**完全可以就地生成迁移**,用 CLI 即可。 > 本机已按此流程实测生成过 `AddAssignedAgentUserIdToFeedback`(`Feedback` 表新增 > 可空列 `AssignedAgentUserId`),产物与既有 EF Core 5.0.17 迁移格式一致。 ### B.0 前置条件(本机现状与坑) | 前置项 | 现状 / 处理 | |--------|-------------| | **dotnet-ef 工具** | 项目未自带。用本地工具清单安装(见 B.1)。 | | **.NET 运行时** | 项目 target `net6.0`;本机可能只装了更高版本(如 .NET 10)。构建不受影响,但运行设计时宿主需 **roll-forward**(见 B.2)。 | | **设计时配置来源** | `FXMigrationsDbContextFactory` 从 `src/iCON.Abp.FX.DbMigrator/appsettings.json` + **Nacos** 读取 `DBConfig` / `ConnectionStrings`。开发机若连不上 Nacos(默认 `192.168.1.120:8848`),需改用**本地优先配置**离线生成(见 B.3)。 | ### B.1 安装 dotnet-ef(本地工具清单,一次性) 在 `AML_Backend/` 目录下: ```bash cd AML_Backend dotnet new tool-manifest # 若已有 .config/dotnet-tools.json 或 dotnet-tools.json 可跳过 dotnet tool install dotnet-ef # 或指定版本:--version "10.*" dotnet ef --version # 验证 ``` > `dotnet-ef` 工具版本可高于项目的 EF Core 版本(本机用 10.0.9 生成 EF Core 5 的迁移没问题)—— > 代码生成用的是**项目引用的 EF Core Design(5.0.\*)**,所以产物仍是 5.0.17 格式,与既有迁移一致。 ### B.2 运行时 roll-forward(仅当本机缺少 net6.0 运行时) `dotnet ef` 会构建启动项目(`net6.0`)并在该运行时里启动设计时宿主。本机若只有 .NET 10, 需允许从 net6 向上滚动到已装的运行时,给命令加环境变量: ```bash DOTNET_ROLL_FORWARD=LatestMajor dotnet ef migrations add ... ``` (若本机已装 .NET 6 运行时,则不需要这个变量。) ### B.3 离线配置:绕开不可达的 Nacos(仅当连不上 Nacos) `FXMigrationsDbContextFactory` 通过 `AddNacosV2ConfigurationLocalFirst()` 读取配置: **本地 `appsettings.json` 里若没有 `NacosConfig` 节点,就完全不连 Nacos、只用本地配置**。 利用这一点,把 `src/iCON.Abp.FX.DbMigrator/appsettings.json` 临时替换为本地优先版本 (去掉 `NacosConfig`,补上 `DBConfig` 与连接串)。 > 生成迁移(`migrations add`)**不会真的连库**,只需连接串可解析(非空)即可; > 指向本机 docker 的 SQL Server 最稳妥。 ```bash cd AML_Backend/src/iCON.Abp.FX.DbMigrator cp appsettings.json appsettings.json.nacos-bak # 备份 cat > appsettings.json <<'JSON' { "DBConfig": { "DBType": "mssql", "ConnectionStringName": "Default" }, "ConnectionStrings": { "Default": "Server=localhost,11433;Database=AbpAML;User Id=sa;Password=Aml@Local2026;TrustServerCertificate=True" } } JSON ``` (`localhost,11433` / `sa` / `Aml@Local2026` 为 `docs/AML_Backend/docker-compose-local-dev` 本地栈的库; 按你的本地环境替换。) **生成完成后务必还原**,避免把本地连接串提交进仓库: ```bash mv -f appsettings.json.nacos-bak appsettings.json ``` ### B.4 生成迁移 在 `AML_Backend/` 目录下执行(项目与启动项目都指向 DbMigrations, 设计时工厂就在其中,`../iCON.Abp.FX.DbMigrator/appsettings.json` 会被正确解析到): ```bash cd AML_Backend DOTNET_ROLL_FORWARD=LatestMajor dotnet ef migrations add \ --project src/iCON.Abp.FX.EntityFrameworkCore.DbMigrations \ --startup-project src/iCON.Abp.FX.EntityFrameworkCore.DbMigrations \ --context FXMigrationsDbContext ``` 看到 `Build succeeded.` + `Done.` 即成功。会生成两文件并更新快照: - `Migrations/<时间戳>_.cs`(`Up`/`Down`) - `Migrations/<时间戳>_.Designer.cs` - `Migrations/FXMigrationsDbContextModelSnapshot.cs`(追加本次模型变更) **核对**:`git diff --stat` 看快照,确认只包含你本次改的实体属性(若夹带了别的变更, 说明工作树里还有未生成迁移的模型改动,需甄别)。 撤销刚生成、尚未应用的迁移: ```bash DOTNET_ROLL_FORWARD=LatestMajor dotnet ef migrations remove \ --project src/iCON.Abp.FX.EntityFrameworkCore.DbMigrations \ --startup-project src/iCON.Abp.FX.EntityFrameworkCore.DbMigrations \ --context FXMigrationsDbContext ``` ### 已生成示例(AssignedAgentUserId) `20260706234441_AddAssignedAgentUserIdToFeedback.cs`: ```csharp protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.AddColumn( name: "AssignedAgentUserId", table: "AMLPortal_Feedbacks", type: "uniqueidentifier", nullable: true); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropColumn( name: "AssignedAgentUserId", table: "AMLPortal_Feedbacks"); } ``` --- ## 注意事项 - 每次修改实体模型后都要生成一个新迁移,并**连同更新后的 `ModelSnapshot` 一起提交**。 - 迁移在下次运行 `DbMigrator` / Host(`Database.Migrate()`)时自动应用到数据库。 - 生成迁移不需要真连库;**应用**迁移才需要连接串正确、且账号有 DDL 权限。 - 别把 B.3 里临时的本地连接串(`appsettings.json`)提交进仓库。