EF单项目如何为开发、生产双库执行迁移并保持结构一致
Blazor WASM多数据库EF Core迁移方案
问题背景
现有Blazor WASM项目在appsettings.json中配置了开发、生产两个数据库连接字符串,生产库为开发库的数据副本,初始配置如下:
"AllowedHosts": "*", "ConnectionStrings": { "SqlConnectionDesarrollo": "Data Source=10.0.0.41;Initial Catalog=QaInventarios;User ID=Innovacion;Password=***;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" "SqlConnectionProduccion": "Data Source=10.0.0.41;Initial Catalog=Inventarios;User ID=Innovacion;Password=***;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" },
Startup中初始硬编码读取开发库连接:
services.AddDbContext<ApplicationDbContext> (options => options.UseSqlServer(Configuration.GetConnectionString("SqlConnectionDesarrollo")));
之前的操作方式为:针对目标数据库手动注释不需要的连接串、修改Startup中读取的连接串名称,再执行迁移命令:
Add-Migration NameMigration Update-Database
该方式下开发库迁移、更新正常,但切换配置后给生产库执行Update-Database时变更不生效,迁移记录不会写入生产库,用Remove-Migration -Force删除迁移重跑也无法解决,最终两个数据库结构不一致。
问题根因
- EF Core会在每个数据库中自动创建
__EFMigrationsHistory系统表,记录所有已应用的迁移版本。手动改硬编码配置的方式极易出现配置读错、本地迁移文件和目标库历史记录不匹配的问题:比如开发库已经应用了新迁移,切生产库时配置未正确生效仍连开发库,或之前误操作删除过迁移文件,EF无法识别待执行的迁移,自然不会更新结构。 - 上述
appsettings.json存在语法错误:两个连接字符串配置项之间缺少逗号,会导致.NET配置解析失败,进一步加剧连接串读取异常的问题。 - 靠修改业务代码切换环境配置属于典型反模式,除了迁移问题外,还容易出现改完配置忘切回、误连生产库写入测试数据的生产事故。
正确实现步骤
1. 修正配置,使用.NET原生多环境配置机制
首先补全appsettings.json的语法错误,两个连接串之间加逗号:
"AllowedHosts": "*", "ConnectionStrings": { "SqlConnectionDesarrollo": "Data Source=10.0.0.41;Initial Catalog=QaInventarios;User ID=Innovacion;Password=***;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", "SqlConnectionProduccion": "Data Source=10.0.0.41;Initial Catalog=Inventarios;User ID=Innovacion;Password=***;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" },
不要在代码里写死要读取的连接串名称,把Startup中的DbContext注册代码改成读取默认连接:
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
新建两个环境专属配置文件,和现有appsettings.json放在同目录:
appsettings.Development.json:开发环境配置,把开发库连接串命名为DefaultConnection写入appsettings.Production.json:生产环境配置,把生产库连接串命名为DefaultConnection写入
运行时.NET会自动根据ASPNETCORE_ENVIRONMENT环境变量加载对应环境的配置,不需要手动改任何代码就能自动切换连接。
2. 迁移操作通过命令参数指定目标,不修改业务代码
核心原则:所有迁移文件只在开发环境生成,永远不要针对生产库执行Add-Migration,保证迁移源唯一
操作流程:
- 开发环境下生成迁移文件,默认加载开发配置,不需要额外参数:
Add-Migration 你的迁移名称
- 先更新开发库,验证迁移逻辑、结构变更是否符合预期:
Update-Database
- 开发库验证通过后,不需要改任何代码/配置,直接通过命令参数指定生产库连接,执行更新:
# 直接指定生产库完整连接串执行更新 Update-Database -Connection "Data Source=10.0.0.41;Initial Catalog=Inventarios;User ID=Innovacion;Password=***;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
如果不想每次输入完整连接串,也可以指定环境和配置里的连接串名称执行:
Update-Database -ConnectionStringName "SqlConnectionProduccion" -Environment Production
3. 已出现结构不一致的修复方案
如果两个库已经出现结构不匹配的问题,按以下步骤重置对齐:
- 先把开发库结构调整到最终正确状态,所有迁移在开发库验证通过
- 登录生产库,清空
__EFMigrationsHistory表中的所有记录,不要删除表本身,不要动业务表数据 - 执行命令重置生产库的迁移状态:
Update-Database -Connection "你的生产库完整连接串" -Migration 0 -Force
- 重新执行生产库更新命令,EF会自动把所有未应用的迁移同步到生产库,并把迁移版本记录写入
__EFMigrationsHistory表,两个库结构即可完全对齐。
注意事项
- 生产库执行迁移前务必备份全量数据,避免迁移逻辑错误导致数据丢失
- 迁移更新失败时优先查看报错信息,不要直接用
Remove-Migration删除迁移文件,绝大多数更新失败都是目标库迁移历史记录和本地迁移文件不匹配导致的 - 迁移文件要纳入代码版本管理,不要随意删除已经应用到生产库的迁移文件
内容的提问来源于stack exchange,提问作者Jasiel Torres
相关产品推荐
相关产品推荐

