db-migration

star 54

指导同时为 MySQL 和 SQL Server 创建数据库迁移。使用数据库特定的 DbContext,处理数据库差异,配置雪花ID。当用户需要创建迁移、修改实体、或遇到迁移错误时使用。

xin-lai By xin-lai schedule Updated 1/24/2026

name: db-migration description: 指导同时为 MySQL 和 SQL Server 创建数据库迁移。使用数据库特定的 DbContext,处理数据库差异,配置雪花ID。当用户需要创建迁移、修改实体、或遇到迁移错误时使用。

多数据库迁移 Skill

快速开始

CodeSpirit 项目支持 MySQL 和 SQL Server 双数据库,必须为每个数据库创建独立的迁移文件。

基本命令

# MySQL 迁移
dotnet ef migrations add MigrationName --context MySql{Service}DbContext --output-dir Data/Migrations/MySql

# SQL Server 迁移
dotnet ef migrations add MigrationName --context SqlServer{Service}DbContext --output-dir Data/Migrations/SqlServer

DbContext 架构

三层继承结构

MultiDatabaseDbContextBase (多数据库基类)
    ↓
{Service}DbContext (服务基础上下文,运行时使用)
    ↓
MySql{Service}DbContext / SqlServer{Service}DbContext (数据库特定上下文,用于迁移)

关键要点

  1. 运行时使用基础 DbContext{Service}DbContext(如 ExamDbContext
  2. 迁移使用特定 DbContextMySql{Service}DbContextSqlServer{Service}DbContext
  3. 数据库差异处理:通过 DatabaseSpecificConfigurations 类统一处理

工作流程

步骤 1:修改实体或配置

修改实体类或实体配置类(IEntityTypeConfiguration<T>)后,准备创建迁移。

步骤 2:检查雪花 ID 配置

如果实体使用 IIdGenerator 生成 ID,必须在实体配置中添加:

builder.Property(x => x.Id).ValueGeneratedNever();

常见错误

Cannot insert explicit value for identity column in table 'Products' 
when IDENTITY_INSERT is set to OFF

解决方案:添加 ValueGeneratedNever() 配置。

步骤 3:为 MySQL 创建迁移

# 切换到 API 项目目录
cd Src/ApiServices/CodeSpirit.{Service}Api

# 创建 MySQL 迁移
dotnet ef migrations add {MigrationName} `
  --context MySql{Service}DbContext `
  --output-dir Data/Migrations/MySql

参数说明

  • --context必须使用 MySql{Service}DbContext
  • --output-dir:指定迁移文件输出目录

步骤 4:为 SQL Server 创建迁移

# 在同一项目目录下
dotnet ef migrations add {MigrationName} `
  --context SqlServer{Service}DbContext `
  --output-dir Data/Migrations/SqlServer

重要:迁移名称应保持一致,但文件会分别存储在 MySql/SqlServer/ 目录下。

步骤 5:验证迁移文件

检查迁移文件是否正确:

  • MySQL 迁移文件在 Data/Migrations/MySql/ 目录
  • SQL Server 迁移文件在 Data/Migrations/SqlServer/ 目录
  • 迁移文件包含正确的数据库特定配置(如 MySQL 的 datetime(6)
  • 雪花 ID 字段配置了 ValueGeneratedNever()(如适用)

步骤 6:应用迁移到本地开发环境

# 应用 MySQL 迁移
dotnet ef database update --context MySql{Service}DbContext

# 应用 SQL Server 迁移
dotnet ef database update --context SqlServer{Service}DbContext

迁移命名规范

场景 命名示例
初始创建 InitialCreate
添加实体 Add{EntityName}
添加字段 Add{FieldName}To{EntityName}
修改字段 Update{FieldName}In{EntityName}
删除字段 Remove{FieldName}From{EntityName}
添加索引 AddIndexTo{EntityName}

数据库差异处理

MySQL 特定配置

通过 DatabaseSpecificConfigurations.ApplyMySqlConfigurations() 自动处理:

  • DateTime:映射为 datetime(6)(微秒精度)
  • 默认值GETUTCDATE()CURRENT_TIMESTAMP(6)
  • 字符串varchar(n) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
  • 长文本:超过 1000 字符使用 text
  • 布尔tinyint(1)
  • Identity 字段:限制最大长度为 256

SQL Server 特定配置

通过 DatabaseSpecificConfigurations.ApplySqlServerConfigurations() 处理:

  • 使用 EF Core 默认配置
  • 仅处理 Identity 字段长度限制(256)

常见错误和解决方案

错误 1:使用了错误的 DbContext

错误信息

No design-time factory found for 'ExamDbContext'

原因:使用了基础 DbContext 而非数据库特定的 DbContext。

解决方案:使用 MySqlExamDbContextSqlServerExamDbContext

错误 2:雪花 ID 配置缺失

错误信息

Cannot insert explicit value for identity column

解决方案:在实体配置中添加 ValueGeneratedNever()

builder.Property(x => x.Id).ValueGeneratedNever();

错误 3:迁移文件位置错误

问题:迁移文件没有按数据库类型分离存储。

解决方案:使用 --output-dir 参数明确指定目录:

--output-dir Data/Migrations/MySql
--output-dir Data/Migrations/SqlServer

实用脚本

validate-migration.ps1

检查迁移是否使用了正确的 DbContext:

# 使用方式
.\Scripts\validate-migration.ps1 -MigrationFile "Data/Migrations/MySql/20260123_AddProduct.cs"

apply-migrations.ps1

一键应用 MySQL 和 SQL Server 迁移:

# 使用方式
.\Scripts\apply-migrations.ps1 -ServiceName "ExamApi"

详见 scripts/ 目录。


检查清单

创建迁移前:

  • 确认实体或配置已修改
  • 检查雪花 ID 配置(如适用)
  • 确认使用正确的 DbContext(MySql{Service}DbContext / SqlServer{Service}DbContext
  • 确认迁移名称符合规范
  • 确认输出目录正确(Data/Migrations/MySql / Data/Migrations/SqlServer

创建迁移后:

  • 验证迁移文件位置正确
  • 检查数据库特定配置是否正确应用
  • 在本地开发环境测试迁移
  • 提交迁移文件到版本控制

最佳实践

  1. 始终使用数据库特定的 DbContext:避免使用基础 DbContext 创建迁移
  2. 迁移文件分离存储:MySQL 和 SQL Server 迁移文件分别存储
  3. 迁移名称保持一致:同一功能的两套迁移使用相同名称
  4. 先创建后应用:先创建迁移文件,验证无误后再应用
  5. 定期同步迁移:确保 MySQL 和 SQL Server 迁移逻辑一致

示例

示例 1:添加新实体

# 1. 创建 Product 实体和配置
# 2. 为 MySQL 创建迁移
dotnet ef migrations add AddProduct `
  --context MySqlMallDbContext `
  --output-dir Data/Migrations/MySql

# 3. 为 SQL Server 创建迁移
dotnet ef migrations add AddProduct `
  --context SqlServerMallDbContext `
  --output-dir Data/Migrations/SqlServer

# 4. 应用迁移
dotnet ef database update --context MySqlMallDbContext
dotnet ef database update --context SqlServerMallDbContext

示例 2:添加字段

# 1. 在 Product 实体中添加 Price 字段
# 2. 创建迁移
dotnet ef migrations add AddPriceToProduct `
  --context MySqlMallDbContext `
  --output-dir Data/Migrations/MySql

dotnet ef migrations add AddPriceToProduct `
  --context SqlServerMallDbContext `
  --output-dir Data/Migrations/SqlServer

相关资源

Install via CLI
npx skills add https://github.com/xin-lai/CodeSpirit --skill db-migration
Repository Details
star Stars 54
call_split Forks 14
navigation Branch main
article Path SKILL.md
More from Creator