Appearance
迁移冲突解决
概述
在团队协作开发中,多个开发者同时创建数据库迁移时容易发生冲突。本文介绍如何预防和解决迁移冲突。
常见冲突场景
场景 1: 重复的迁移名称
Developer A creates: 20240101_AddProductTable.cs
Developer B creates: 20240101_AddProductTable.cs (冲突!)解决方案: 使用有意义的唯一命名
bash
# ❌ 不好的命名
dotnet ef migrations add Update
# ✅ 好的命名
dotnet ef migrations add AddPriceColumnToProducts
dotnet ef migrations add CreateOrderItemsTable场景 2: 迁移顺序冲突
主分支: Migration_001 → Migration_002
开发者A: Migration_001 → Migration_002 → Migration_A
开发者B: Migration_001 → Migration_002 → Migration_B
合并后冲突!解决方案: 重新基于最新主分支生成迁移
bash
# 1. 拉取最新主分支
git pull origin main
# 2. 删除本地冲突的迁移
dotnet ef migrations remove
# 3. 重新生成迁移(会自动追加到末尾)
dotnet ef migrations add MergeWithLatestChanges
# 4. 验证迁移
dotnet ef database update预防策略
1. 团队规范
markdown
## 迁移命名规范
- 格式: `{YYYYMMDD}_{Description}`
- 示例: `20240115_AddUserPreferencesTable`
## 提交流程
1. 拉取最新代码
2. 检查是否有未应用的迁移
3. 创建自己的迁移
4. 测试迁移成功
5. 提交代码前再次拉取并更新2. CI/CD 检查
yaml
# .github/workflows/migration-check.yml
name: Migration Check
on: [pull_request]
jobs:
check-migrations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Apply migrations
run: dotnet ef database update
env:
ConnectionStrings__Default: ${{ secrets.TEST_DB }}
- name: Check for pending changes
run: |
PENDING=$(dotnet ef migrations has-pending-model-changes)
if [ "$PENDING" = "True" ]; then
echo "Error: Model has pending changes. Please create a migration."
exit 1
fi解决冲突
方法 1: 手动合并迁移文件
csharp
// 冲突的迁移 A
public partial class AddEmailToUsers : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Email",
table: "Users",
type: "nvarchar(200)",
nullable: true);
}
}
// 冲突的迁移 B
public partial class AddPhoneToUsers : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Phone",
table: "Users",
type: "nvarchar(20)",
nullable: true);
}
}
// ✅ 合并后的迁移
public partial class AddContactInfoToUsers : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
// 合并两个迁移的操作
migrationBuilder.AddColumn<string>(
name: "Email",
table: "Users",
type: "nvarchar(200)",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Phone",
table: "Users",
type: "nvarchar(20)",
nullable: true);
}
}方法 2: 重置迁移历史
bash
# ⚠️ 仅在开发环境使用!
# 1. 删除所有迁移文件
rm Migrations/*.cs
# 2. 删除 __EFMigrationsHistory 表
dotnet ef database drop -f
dotnet ef database update
# 3. 重新创建初始迁移
dotnet ef migrations add InitialCreate
# 4. 应用到数据库
dotnet ef database update最佳实践
✅ 推荐做法
- 频繁同步: 每天多次拉取主分支
- 小步迁移: 每次只做一个小的改动
- 及时沟通: 修改共享表前与团队沟通
- 自动化测试: CI/CD 自动应用迁移
- 文档化: 记录复杂迁移的目的
❌ 避免的陷阱
- 不要修改已提交的迁移: 创建新迁移来修正
- 不要删除共享的迁移: 会影响其他人的数据库
- 不要忽略冲突: 立即解决,不要拖延
- 不要在迁移中写业务逻辑: 只做架构变更
总结
| 策略 | 效果 | 难度 |
|---|---|---|
| 规范命名 | ⭐⭐⭐ 中 | ⭐ 低 |
| 频繁同步 | ⭐⭐⭐⭐ 高 | ⭐ 低 |
| CI/CD 检查 | ⭐⭐⭐⭐⭐ 高 | ⭐⭐ 中 |
| 小步迁移 | ⭐⭐⭐⭐ 高 | ⭐⭐ 中 |
关键: 预防为主,及时沟通,自动化检测!