Files

222 lines
7.6 KiB
Markdown
Raw Permalink Normal View History

# MiGu.DB Migrations 使用手册
面向日常改表、发版与排错。当前默认 Provider 为 **Sqlite**,迁移目录为 `Migrations/Sqlite/`
---
## 1. 概念速览
| 概念 | 说明 |
|------|------|
| Migration | 一次 Schema 变更(建表/加列/索引等),对应一对 `*_Name.cs` + `*_Name.Designer.cs` |
| ModelSnapshot | `MiGuDbContextModelSnapshot.cs`,当前模型总快照;下次 `add` 时与代码模型做 diff |
| `__EFMigrationsHistory` | 数据库内表,记录已应用的 Migration Id |
| DataMigrator | **数据**修补(刷旧状态、回填列),不是 Schema;启动时在 Migrate 之后执行 |
**原则:Schema 只走 Migrations;业务代码禁止手写 CREATE/ALTER。**
三个文件职责:
- `YYYYMMDDHHMMSS_Name.cs``Up()`/`Down()`,真正改库
- `YYYYMMDDHHMMSS_Name.Designer.cs` → 该次迁移的目标模型元数据(勿手改)
- `MiGuDbContextModelSnapshot.cs` → 全库最新快照(勿手改,除非处理合并冲突)
---
## 2. 环境准备
### 2.1 工具
仓库根目录(`Migu2.0`)执行:
```powershell
# 全局工具(任选)
dotnet tool install --global dotnet-ef --version 8.0.10
# 或本地工具目录(本仓库曾用此方式)
dotnet tool install dotnet-ef --version 8.0.10 --tool-path .\.tools
.\.tools\dotnet-ef --version
```
版本需与项目 EF Core **8.0.x** 对齐。
### 2.2 工程关系
| 参数 | 值 |
|------|-----|
| 迁移所在工程 | `MiGu.DB` |
| 启动工程 | `MiGu.Server`(提供配置与 Design 包) |
| DbContext | `MiGu.DB.Kernel.Context.MiGuDbContext` |
| Design-time 工厂 | `MiGu.DB.Kernel.Design.MiGuDbContextFactory` |
`MiGu.Server.csproj` 已引用 `Microsoft.EntityFrameworkCore.Design``MiGu.DB` 含 Sqlite 等 Provider 包。
---
## 3. 生成 Migration(日常流程)
### 3.1 改模型
`MiGu.DB/Domains` 改实体或 `IEntityTypeConfiguration`,保存后编译通过:
```powershell
dotnet build .\MiGu.DB\MiGu.DB.csproj
```
### 3.2 添加迁移
在**解决方案根目录**执行(PowerShell):
```powershell
dotnet ef migrations add <迁移名称> `
--project .\MiGu.DB\MiGu.DB.csproj `
--startup-project .\MiGu.Server\MiGu.Server.csproj `
--output-dir Migrations/Sqlite `
--namespace MiGu.DB.Migrations.Sqlite `
--context MiGuDbContext
```
命名建议(PascalCase,无空格):
| 场景 | 示例名 |
|------|--------|
| 首库 | `InitialPlatform`(已存在,勿重复) |
| 加表 | `AddWmsXxxTable` |
| 加列 | `AddStoragePriorityColumn` |
| 加索引 | `AddStockEventOperatedAtIndex` |
### 3.3 生成后检查(必做)
1. 新文件应在:`MiGu.DB/Migrations/Sqlite/`
2. 打开 `*_Name.cs`,确认 `Up()` 只包含**本次预期**变更(无误删表、无多余重建)
3. 确认 `MiGuDbContextModelSnapshot.cs` 仍在 `Migrations/Sqlite/`
- 若出现在 `MiGu.DB/MiGu/DB/Migrations/Sqlite/` 等错误路径:把 Snapshot **移回**正确目录并删掉空目录(`--namespace` 偶发路径问题)
### 3.4 应用到本地库
启动 `MiGu.Server` 即可(`Program.cs` 直接调用 `MigrateMiGuDbAsync`),或:
```powershell
dotnet ef database update `
--project .\MiGu.DB\MiGu.DB.csproj `
--startup-project .\MiGu.Server\MiGu.Server.csproj `
--context MiGuDbContext
```
---
## 4. 常用命令
```powershell
# 列出迁移
dotnet ef migrations list `
--project .\MiGu.DB\MiGu.DB.csproj `
--startup-project .\MiGu.Server\MiGu.Server.csproj `
--context MiGuDbContext
# 生成 SQL 脚本(发版/DBA 审阅,不直接连库执行也可)
dotnet ef migrations script `
--project .\MiGu.DB\MiGu.DB.csproj `
--startup-project .\MiGu.Server\MiGu.Server.csproj `
--context MiGuDbContext `
--output .\MiGu.DB\Migrations\Sqlite\script.sql
# 从某迁移到最新(含幂等脚本时加 --idempotent
dotnet ef migrations script FromMigration ToMigration `
--project .\MiGu.DB\MiGu.DB.csproj `
--startup-project .\MiGu.Server\MiGu.Server.csproj `
--context MiGuDbContext `
--idempotent
# 删除「尚未应用到任何重要库」的最后一次迁移(仅开发)
dotnet ef migrations remove `
--project .\MiGu.DB\MiGu.DB.csproj `
--startup-project .\MiGu.Server\MiGu.Server.csproj `
--context MiGuDbContext
# 回滚到指定迁移(会执行 Down,生产慎用)
dotnet ef database update <目标迁移名> `
--project .\MiGu.DB\MiGu.DB.csproj `
--startup-project .\MiGu.Server\MiGu.Server.csproj `
--context MiGuDbContext
```
使用本地工具时,将 `dotnet ef` 换成 `.\.tools\dotnet-ef`
---
## 5. 启动时发生了什么
**完整说明(顺序、配置、SchemaMode、开发注意)见:**
**[MiGu.Server/README.md · 数据库启动流程](../MiGu.Server/README.md#数据库启动流程)**
摘要:`MigrateMiGuDbAsync``Database:SchemaMode``EnsureCreated``Migrate`;之后按需跑 `IDataMigrator`
**Migrate 基线:** 已有表、无 History 时,会把**全部** pending Migration 写入 `__EFMigrationsHistory`(假定 EnsureCreated 库已对齐模型 tip)。发版前若开发期改过模型,须先 `migrations add` 再切 `Migrate`
---
## 6. Schema 变更 vs 数据修补
| 需求 | 做法 |
|------|------|
| 新表/新列/索引/改列类型 | `migrations add` → 提交迁移文件 |
| 刷旧枚举字符串、回填列 | 新增 `IDataMigrator`,注册到 `AddMiGuDataMigrators` |
| 开发机整库清空重来 | 删 `data/platform.db*` 后启动(等同空库 Migrate);**不要**在生产用 EnsureDeleted |
注意:带 `HasConversion` 的枚举列,用 `ExecuteUpdate` + 原始字符串比较可能触发转换异常;空 LayoutMode 等特例用 raw UPDATE(参见 `AreaLayoutModeDefaultMigrator`)。
---
## 7. 协作与发版
1. **迁移文件必须入库**(含 Designer、Snapshot
2. 多人同时改模型易冲突 Snapshot:保留一方迁移,另一方 `remove` 后基于最新代码重新 `add`
3. 已合并到主分支并可能已应用到共享库的迁移:**不要** `migrations remove` 或改写历史 `Up()`
4. 发版包随程序集带上 Migration;现场首次升级靠启动 Migrate(或预执行 `migrations script`
---
## 8. 其他 Provider(预留)
`IDbProviderSetup` 已预留 MySql / Npgsql / SqlServer。首轮只有 Sqlite 迁移套。
将来为企业库生成独立套时:
```powershell
# 示例:输出到 Migrations/MySqlnamespace 同步修改
dotnet ef migrations add InitialPlatform `
--project .\MiGu.DB\MiGu.DB.csproj `
--startup-project .\MiGu.Server\MiGu.Server.csproj `
--output-dir Migrations/MySql `
--namespace MiGu.DB.Migrations.MySql `
--context MiGuDbContext
```
并确保对应 Provider 的 `MigrationsAssembly` / 运行时能发现该套迁移(按需拆程序集或过滤命名空间)。
---
## 9. 常见问题
| 现象 | 处理 |
|------|------|
| `dotnet ef` 找不到 | 安装 8.0.10 工具,或用 `.\.tools\dotnet-ef` |
| Design-time 连错库 | 检查 `MiGuDbContextFactory`(默认 `platform.db`);运行时以 Server 配置为准 |
| Snapshot 生成到奇怪目录 | 移回 `Migrations/Sqlite/` |
| 旧库启动重复建表失败 | 确认基线逻辑是否写入 History;备份后必要时手工插入 Initial 行 |
| 改完实体 `add` 生成空迁移 | 模型无差异或未编译;先 `dotnet build` |
| 想撤销未提交的迁移 | `migrations remove`(确认未被他人/现场应用) |
---
## 10. 检查清单(每次提 PR)
- [ ] `dotnet build` 通过
- [ ] 新迁移仅含预期 DDL
- [ ] 文件在 `Migrations/Sqlite/`Snapshot 路径正确
- [ ] 本地启动一次,确认 Migrate 成功
- [ ] 若有数据刷库,已加幂等 `IDataMigrator` 并注明 Order
- [ ] 未改写已发布的历史 Migration