我创建了一个新的.Net 5项目,并希望使用EF Core。我使用自动生成了多个migration.cs文件
dotnet ef migrations add MyMigration
并希望应用它们(用于开发和生产)。我知道MigrateAsync
方法,所以我读到了如何在启动时调用这个方法
https://andrewlock.net/running-async-tasks-on-app-startup-in-asp-net-core-part-1/
但无论我读到哪里,都不应该将这种方法用于生产,因为这些迁移不会在单个事务中执行(错误时不会回滚)。
不幸的是,无论环境如何,都没有太多关于如何做到这一点的资源,我发现了这篇文章
https://www.thereformedprogrammer.net/handling-entity-framework-core-database-migrations-in-production-part-2
一个选项可以是控制台应用程序调用迁移
https://www.thereformedprogrammer.net/handling-entity-framework-core-database-migrations-in-production-part-2/#1b-调用上下文数据库迁移通过控制台应用程序或管理员命令
但我无法理解这种方法的区别,因为它没有解决事务性问题?
在开发/生产过程中应用迁移的最佳做法是什么?
-
在自动生成迁移之后,我非常喜欢简单性,
dotnet ef database update
是工作吗?我不需要使用其他工具? -
创建一个控制台应用程序,从迁移中生成.sql文件,安装DbUp并将其用于迁移部分?
什么最有效在很大程度上取决于部署管道的工作方式——生产前有多少环境,发布周期,部署的哪些部分是自动化的。不存在通用的";最佳实践"-每种处理迁移的方法都有自己的权衡。根据您的需求和期望选择升级程序。
当为一个中型项目(大约70个表)设置EF Core迁移时,我尝试了一些潜在的方法。我对这个过程的观察以及最终的结果:
- 您希望在更改模型和部署到生产环境之间获得迁移SQL,哪怕只是为了防止出现任何可能导致回滚问题的破坏性更改。我们决定使用dbcontext直接在项目中进行迁移,并为每个可能部署到任何环境的构建生成一个迁移脚本(使用
dotnet ef migrations script --idempotent
)——在我们的案例中,为每个推送到主干或发布分支生成一个CI步骤 - 将迁移SQL置于版本控制中,并将SQL视为数据库结构方面的真相来源,当您希望保留某些列用于备份或向后兼容性时,可以手动修改脚本。另一种选择是将您的数据模型视为数据库模式的参考,并将迁移SQL视为不保留的中间步骤,这使整个过程更容易自动化,但需要您直接在数据模型中处理特殊情况
- 在生成迁移脚本时使用
--idempotent
标志可以为您提供一个脚本,您可以将该脚本重新应用到数据库模式,而不管它的模式版本是什么,让它只执行尚未执行的步骤。这意味着您可以在不破坏架构的情况下,将相同的迁移脚本重新应用于已迁移的数据库。如果您的应用程序的不同版本在不同的环境(开发、暂存和生产环境)中并行运行,则可以手动跟踪需要应用的迁移脚本版本以及顺序,从而避免问题 - 当您有迁移SQL时,您可以使用本机数据库工具,以便将它们应用于目标环境,例如
sqlcmd
用于SQL Server,psql
用于postgres。这还有一个好处,即让具有更高权限(模式修改)的单独用户处理迁移,而您的应用程序使用的权限有限,通常无法触及模式 - 应用数据库迁移是应用程序部署的一部分,而不是应用程序启动的一部分-如果您有某种部署自动化,那么它可能是针对目标数据库执行迁移的最佳场所,同样,数据库本机客户端是
DbUp
的一个很好的替代方案,您可以选择任何一个。将迁移与应用程序启动分离还使您能够针对不匹配但仍然兼容的数据库模式运行应用程序,这在进行部署时非常方便 - 架构升级的大多数问题都来自于破坏版本之间的架构兼容性-避免这种情况需要在处理数据模型时注意向后/向前兼容性,并将破坏性更改拆分为单独的版本,以保持至少一步的向后/向前兼容-是否需要取决于您的项目,这是你应该决定的。我们针对当前数据库架构运行前一版本的完整集成测试套件,针对当前版本针对前一数据库架构运行完整集成测试套装,以确保在两个后续版本之间不会引入突破性的更改-任何移动多个版本的部署都会逐一进行迁移,假设迁移脚本或应用程序启动可以包括从旧模型到新模型的数据转换
总之:生成迁移SQL并在版本部署时使用本机工具或DbUp可以在一定程度上手动控制迁移过程,并且可以通过自动化部署过程来实现易用性。出于开发目的,您还可以在应用程序启动时添加自动迁移,最好仅在环境设置为Development
时应用——只要团队中的每个人都有自己的开发数据库(本地SQL、共享服务器上的个人数据库、如果使用SQL则为filedb),就不必担心冲突。