指导同时为 MySQL 和 SQL Server 创建数据库迁移。使用数据库特定的 DbContext,处理数据库差异,配置雪花ID。当用户需要创建迁移、修改实体、或遇到迁移错误时使用。
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
MultiDatabaseDbContextBase (多数据库基类)
↓
{Service}DbContext (服务基础上下文,运行时使用)
↓
MySql{Service}DbContext / SqlServer{Service}DbContext (数据库特定上下文,用于迁移)
{Service}DbContext(如 ExamDbContext)MySql{Service}DbContext 或 SqlServer{Service}DbContextDatabaseSpecificConfigurations 类统一处理修改实体类或实体配置类(IEntityTypeConfiguration<T>)后,准备创建迁移。
如果实体使用 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() 配置。
# 切换到 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:指定迁移文件输出目录# 在同一项目目录下
dotnet ef migrations add {MigrationName} `
--context SqlServer{Service}DbContext `
--output-dir Data/Migrations/SqlServer
重要:迁移名称应保持一致,但文件会分别存储在 MySql/ 和 SqlServer/ 目录下。
检查迁移文件是否正确:
Data/Migrations/MySql/ 目录Data/Migrations/SqlServer/ 目录datetime(6))ValueGeneratedNever()(如适用)# 应用 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} |
通过 DatabaseSpecificConfigurations.ApplyMySqlConfigurations() 自动处理:
datetime(6)(微秒精度)GETUTCDATE() → CURRENT_TIMESTAMP(6)varchar(n) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_citexttinyint(1)通过 DatabaseSpecificConfigurations.ApplySqlServerConfigurations() 处理:
错误信息:
No design-time factory found for 'ExamDbContext'
原因:使用了基础 DbContext 而非数据库特定的 DbContext。
解决方案:使用 MySqlExamDbContext 或 SqlServerExamDbContext。
错误信息:
Cannot insert explicit value for identity column
解决方案:在实体配置中添加 ValueGeneratedNever():
builder.Property(x => x.Id).ValueGeneratedNever();
问题:迁移文件没有按数据库类型分离存储。
解决方案:使用 --output-dir 参数明确指定目录:
--output-dir Data/Migrations/MySql
--output-dir Data/Migrations/SqlServer
检查迁移是否使用了正确的 DbContext:
# 使用方式
.\Scripts\validate-migration.ps1 -MigrationFile "Data/Migrations/MySql/20260123_AddProduct.cs"
一键应用 MySQL 和 SQL Server 迁移:
# 使用方式
.\Scripts\apply-migrations.ps1 -ServiceName "ExamApi"
详见 scripts/ 目录。
创建迁移前:
MySql{Service}DbContext / SqlServer{Service}DbContext)Data/Migrations/MySql / Data/Migrations/SqlServer)创建迁移后:
# 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
# 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