【问题标题】:.NET Rails-style Database Migrations with Feature Branching具有功能分支的 .NET Rails 样式数据库迁移
【发布时间】:2012-08-22 01:35:28
【问题描述】:

我查看了.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 进行源代码控制。注意我已经看到了标题为Database migrations in a complex branching system 的帖子,但它并没有真正提供答案。

【问题讨论】:

    标签: .net git database-migration rails-migrations


    【解决方案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 个字符,这通常足以让它变得独一无二。

    总结

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

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

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

    【讨论】:

      猜你喜欢
      • 2010-10-08
      • 2011-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-11
      • 1970-01-01
      • 1970-01-01
      • 2011-02-11
      相关资源
      最近更新 更多