今天,EF Core团队想向你介绍一个新的功能,它在我们最新的预览版中发货:迁移包。
商业应用随着时间的推移而不断发展。这些变化反映在你的代码、模式和数据中。代码的更新通常可以通过替换二进制文件或将负载均衡器指向新的节点来简单部署。另一方面,涉及数据库变化的更新不可避免地更加复杂。不仅代码和数据需要保持同步,而且对模式定义的改变也会引起副作用,从而影响到整个表。现有列中的数据可能需要进行转换,甚至在应用变化的时候进行转移,而现代的应用程序被期望在最小的停机时间内运行。
使用EF Core的一个主要好处是能够通过一种叫做*迁移的*机制来管理模式变化。迁移本质上是对你的数据库模型的一个 "时间点 "的小型快照。在对你的模型进行了可能会改变模式的修改之后,你可以使用EF Core的命令行界面(CLI)来捕获迁移中的快照。然后,同一工具可以用来将迁移指向一个现有的数据库,并部署必要的数据定义语言(DDL),使数据库与模型同步。
迁移必须能够看到数据库模型才能工作。当你创建或应用一个迁移时,包含迁移的项目和 DbContext定义的项目被编译和检查。在高层次上,迁移的功能是这样的:
- 当一个数据模型被引入时,开发人员使用EF Core工具添加一个相应的迁移,描述必要的更新以保持数据库模式的同步。EF Core将当前模型与旧模型的快照进行比较,以确定差异,并生成迁移源文件;这些文件可以像其他源文件一样在项目的源控制中被跟踪。
- 一旦生成了一个新的迁移,就可以通过各种方式将其应用到数据库中。EF Core在一个特殊的历史表中记录了所有已应用的迁移,使它能够知道哪些迁移已被应用,哪些未被应用。
到目前为止,在部署新版本的软件时,传统上有三种开发者应用迁移的方式。
脚本
一种方法是使用EF Core工具从迁移中生成SQL脚本。这样做的好处是,在部署之前,可以对脚本进行检查和必要的修改。脚本是纯SQL语言,可以独立于EF Core进行管理和部署,无论是通过自动流程还是数据库管理员(DBA)的手动干预。默认情况下,脚本是针对它们所产生的迁移的,并假定你已经应用了以前的变化。它们必须按顺序运行,否则脚本可能会失败并产生意想不到的副作用。
第二种选择是生成同位素的脚本。这些脚本会检查现有的版本,并根据需要应用多次迁移,以使数据库处于最新状态。这两种方法都有取舍,但是idempotent选项是最安全的方法,可以有一个一刀切的脚本。
命令行界面(CLI)
可以直接使用命令行工具来部署更新。这有一定的风险,因为变化会立即被部署,而不给你检查生成的迁移的机会。这也需要在生产服务器上安装工具的依赖项(.NET SDK、你的源代码来编译模型和工具本身)。
应用程序的启动
我们可以通过调用Database.Migrate() 方法,将迁移作为应用程序的一部分来运行。尽管这可能会起作用,但这种方法是有问题的。在分布式系统中,如果多个节点同时启动,它们可能会相互冲突,试图同时升级或针对部分更新的数据库进行迁移。修改模式需要应用程序有较高的权限,但授予这些权限是一种安全风险。与CLI方法一样,在应用SQL之前没有机会审查它。
引入迁移捆绑程序
脚本仍然是迁移的一个可行的选择。对于那些选择代码方式的用户来说,为了减少与命令行和应用程序启动方式相关的一些风险,EF Core团队很高兴地宣布,在EF Core 6.0预览版7中可以预览迁移包。 迁移包执行的操作与命令行界面相同:
dotnet ef database update
迁移包是一个独立的可执行文件,包含了运行迁移所需的一切。它接受连接字符串作为一个参数。它旨在成为持续部署中使用的工件,可以与所有主要工具(Docker、SSH、PowerShell等)一起使用。它不需要你复制源代码或安装.NET SDK(只有运行时),可以作为部署步骤集成到你的DevOps管道中。这也使迁移活动与你的主应用程序解耦,因此不存在对竞赛条件的担忧,也不需要提升你的主应用程序的权限。我们的愿景是在Visual Studio和GitHub Actions等DevOps工具集中拥有使用迁移包的一流构建块。目前,我们提供捆绑包,你负责运行它。
开始使用
要使用捆绑包,你至少需要预览版7的工具。你可以用这个命令来安装它:
dotnet tool install --global dotnet-ef --version 6.0.0-preview.7.21378.4
你已经安装了这个工具吗?没问题!只需将install 替换为update 来升级:
dotnet tool update --global dotnet-ef --version 6.0.0-preview.7.21378.4
在命令行中,在包含EF Core迁移的项目工作目录下,使用:
dotnet ef migrations bundle
来生成捆绑包。如果你喜欢使用Visual Studio Package Manager Console,可以运行这个命令:
Bundle-Migration
这两个选项都会产生一个名为bundle (即Windows机器上的bundle.exe )的工件。
默认情况下,捆绑包将寻找一个appSettings.json ,以找到连接字符串。只需运行:
./bundle.exe
来部署你的迁移程序。如果你喜欢用环境变量代替,只需使用--connection 开关传递连接字符串。比如说:
./bundle --connection {$ENVVARWITHCONNECTION}
很明显(我们希望),在将其应用于生产之前,将捆绑包作为你的暂存和测试过程的一部分来部署是有意义的。
注意:迁移是EF Core根据模型的模式和形状对所需变化的 "最佳猜测"。你应该在应用迁移之前总是检查它,并根据需要进行更新/定制。例如,如果你决定将一个
Name列拆分为FirstName和LastName,EF Core将产生变化,删除一个列并添加另外两个列,但是你需要自定义迁移,用旧列中的数据填充新列。
你的反馈很重要
捆绑的工作还有待完成,我们需要你的帮助。你可以通过两种主要方式为这项功能做出贡献:
感谢你一直以来的支持,我们期待着你的反馈!