1

我查看了.NET Migrations Engine上的所有选项,发现使用 Rails 样式迁移的引擎是最有趣的,主要是因为它们以与数据库无关的方式编写,可以轻松用于不同的数据库平台。

然而,我看到了一个明显的问题,他们似乎都没有开箱即用地解决:源代码控制分支。

情景

  1. 功能 1 正在 branch1 上开发,并在名为 column1 的表中添加一列
  2. 功能 2 正在 branch2 上开发,并向名为 column2 的同一个表添加一列
  3. 发行版 1.1 包含功能 2,但功能 1 尚未完成
  4. 功能1完成并合并到主干
  5. 发布了 1.2 版,但是进入主干的新 column1 字段是版本 1(直接在代码中与 1.1 版绑定),因此在迁移时不会在数据库中更新

使用Migrator.NET等工具,问题似乎是迁移版本与实际软件版本相关,而不是 SCC 提交。但是,该属性必须添加到源代码管理中的代码中。我已经看到使用日期而不是版本的示例,但这似乎并不能解决手头的问题,而不是增量版本控制。

我找到的最接近答案的是Liquibase FAQ page,但是对于 .NET 中的 Rails 样式框架,该解决方案需要更改代码(即使在Rik Migrations中,其结构类似于 liquibase 更改日志文件的属性) :

Liquibase 是否适用于分支机构? 是的。由于每个更改都是独立的,因此在不同分支中进行的数据库更改然后合并将在下次运行 Liquibase 时运行。您可能会遇到语句运行顺序的问题,但您遇到的任何问题都可以通过重新排序更改日志文件轻松解决。

处理此问题的典型方法是什么?

如果有什么不同,我使用 Git 进行源代码控制。注意我已经看过题为“复杂分支系统中的数据库迁移”的帖子,但它并没有真正提供答案。

4

1 回答 1

1

我已经对此进行了一些思考,这就是我到目前为止的想法。我还没有决定迁移框架,但下面的方法假设像Migrator.NET那样使用属性。但是,这也可以适用于其他迁移者。

由于问题在于迁移版本过早(在开发期间而不是在发布期间),我的第一直觉是想出一个工作流,以确保在发布之前无法对迁移进行版本控制。这可以通过构建脚本、单元测试和源代码控制来完成。以下是步骤:

  1. 创建一个单元测试,当 MigrationAttributes 存在版本高于 CI 过程中运行的当前数据库版本时失败
  2. 创建一个单元测试,当对任何迁移的更改等于或低于在 CI 过程中运行的当前数据库版本时失败
  3. 在 CI 构建之前添加一个步骤,该步骤定位从 Migration 类继承的所有类,并添加版本 1 高于当前数据库版本的 MigrationAttribute。这可确保迁移将在 CI 过程中成功运行。确保在此步骤之前运行步骤 1 和 2 中的单元测试。
  4. 在 CI 构建之后添加一个步骤,将数据库表中的当前数据库版本设置回当前发布的数据库版本。我们的 CI 流程数据库版本控制只是临时的。
  5. 在发布构建之前添加一个步骤,该步骤定位从 Migration 类继承的所有类,并添加版本 1 高于当前数据库版本的 MigrationAttribute。将此代码更改提交回主干。

这里的共同前提是所有这些都可以完全自动化,并且数据库迁移版本属性作为临时 CI 构建步骤和发布步骤添加(通过构建过程,而不是手动)。单元测试确保在开发周期中过早编辑迁移或版本化它们不会作弊。

当然,步骤 3 和 4 可以替换为 CI 过程中的删除/重新创建方法,它可能会更可靠。关键是数据库版本控制在发布期间发生并被检查到源代码控制中(以前从未如此)。

版本控制

为了适应这个工作流程,我正在考虑将数据库版本作为 AssemblyInformationalVersion 属性的一部分

[assembly: AssemblyVersion("1.2.0.0")]
[assembly: AssemblyFileVersion("1.2.3.4")]
[assembly: AssemblyInformationalVersion("1.2.3.4+<GitHash>-<DBVersion>")]

所以在上面的例子中,数据库的版本会在Assembly之后插入。这将允许我使用常规的主要/次要 + 构建版本,而且还可以在程序集中跟踪当前构建的数据库发布版本(以及 Git 中的头部提交)。然后发布过程可以相应地增加这个版本,所有的单元测试和其他步骤都会随之而来。请注意,AssemblyInvormationalVersion 在 Windows 中显示为产品版本。

GitHash 只是前 7 个字符,这通常足以让它变得独一无二。

概括

主要的一点是分支可以在不影响数据库发布的情况下尽可能复杂,因为源代码不会在任何分支中包含数据库版本控制属性(如果包含,构建将失败) . 但是,分支将包含迁移数据库所需的信息,这实际上是一个开发步骤,而不是发布步骤。

显然,单元测试和构建脚本将需要反射、代码注入以及与源代码控制提供者合作以确保遵循规则,但这一切都是可能的。

我还没有在实践中测试过这个,但是如果我找不到另一个解决方案,这可能是我要走的方向。

于 2012-08-27T17:25:05.337 回答