持续部署的 EF Core Code First 运行时迁移回滚策略

Mat*_*ler 6 c# entity-framework database-migration entity-framework-core entity-framework-migrations

我有一项在启动时使用 EF Core 运行时迁移的服务:

var migrator = dbContext.Database.GetService<IMigrator>();
await migrator.MigrateAsync("targetMigration", cancellationToken);
Run Code Online (Sandbox Code Playgroud)

为了生成迁移,我首先更新 DbContext 类,然后执行“dotnet ef migrations add”来生成迁移代码。

迁移发生后,部署的升级可能会自动回滚到以前的版本。例如,如果健康检查或测试失败。在这种情况下,我希望应用程序的先前版本能够自动回滚迁移。我知道 MigrateAsync 可以恢复迁移,但在我当前的工作流程中,迁移代码不会出现在以前版本的代码中,因此我不确定它是否能够恢复迁移。

我可以想到这样的工作流程:

  1. 更改 DbContext 并运行“dotnet ef add migration”以生成迁移代码

  2. 恢复 DbContext 更改并部署应用程序,以便迁移代码“n”存在,但 MigrateAsync 中的目标迁移和 DbContext 的版本为“n-1”

  3. 重新应用 DbContext 更改,将 MigrateAsync 更改为目标迁移“n”,然后部署应用程序

但这似乎很尴尬,我不确定是否有必要,以及是否一定有效。

使用 EF Core 部署代码优先运行时迁移的好策略是什么,这样如果部署了以前的版本,迁移可以自动回滚?

rek*_*m87 2

据我所知,EF没有为你的情况准备任何东西,在生产环境中来回迁移确实很困难,而且你必须考虑到多次迁移可能会造成数据丢失。

首先,当必须很好地测试更改时,您需要创建一个流程,当更改进入生产时,您应该 99% 确定生产中不会出现回滚。

正如您所说,您将需要最新版本的代码,如果没有,EF 将不知道“down”应该做什么。

在我们当前的系统中,我们分析每个迁移,如果是新表或简单的东西,我们只需从 CI 运行迁移。如果它是更复杂的东西,或者我们需要更复杂的移动(具有数百万行的表修改),我们只需手动完成,因此我们可以将数据发送到临时表,填充空数据或使用我们刚刚生成的特殊函数编写脚本并使用它。

dotnet ef migrations script 20190725054716_Add_new_tables
Run Code Online (Sandbox Code Playgroud)

这是一个非常困难的问题,Java 和 JPA 共享相同的问题来生成历史记录。

这些迁移生成器非常适合开发,但对于生产、不断变化的环境来说却很困难,特别是当您需要像您一样来回移动时,另一种选择是使用其他工具来处理为这种情况做好更好准备的迁移,例如liquibase

另一个想法可以在这里找到:

我最终创建了一个自定义工具,可以智能地执行迁移并自动确定用于迁移的模型(上下文)程序集。