EF Core 7:后端与测试并发调用EnsureCreated/Migrate的问题咨询
统一迁移执行入口,禁止多进程并行触发
不要让后端服务和测试套件同时执行迁移操作。选一个单一执行源:比如仅让后端启动时执行Migrate(),测试套件只做架构版本验证——通过context.Database.GetPendingMigrations()检查是否有未应用的迁移,若存在则直接抛出错误提示,要求先完成迁移再运行测试;或者将迁移操作提前到CI/CD流程中执行,后端和测试都只读取已同步的数据库架构,不再自行触发迁移。移除
EnsureCreated(),仅用Migrate()维护架构EnsureCreated()会直接创建数据库架构但不会写入迁移历史表,而Migrate()是基于历史记录的增量更新,两者同时使用本身就会导致架构状态冲突。完全移除EnsureCreated(),全程依赖Migrate()来初始化和更新数据库架构,从根源避免两种机制的冲突。通过分布式锁控制迁移的串行执行
利用SQL Server的sp_getapplock存储过程实现分布式锁,确保同一时间只有一个进程能执行迁移操作。在后端启动或测试套件准备执行迁移前,先调用该存储过程获取锁(设置合理的超时时间),拿到锁后再执行Migrate(),操作完成后释放锁。即使多进程并发触发,也能保证迁移操作串行执行,避免架构不一致。为测试环境分配独立数据库
让后端服务和测试套件使用完全隔离的数据库实例:后端连接开发/生产级数据库,测试使用专属的测试数据库。测试套件可以在测试开始前自行初始化数据库、执行迁移,测试结束后按需清理数据或重置数据库,从物理层面隔离两者的操作,彻底避免并发冲突。确保迁移脚本的幂等性
自定义迁移脚本时,添加幂等性判断逻辑(比如用IF NOT EXISTS检查对象是否已存在)。EF Core默认生成的迁移脚本大多具备幂等性,但自定义部分需要额外处理,这样即使迁移被重复触发,也不会因对象已存在等问题抛出错误。
内容的提问来源于stack exchange,提问作者Cristiano Ghersi

