具有功能分支的.NET Rails风格的数据库迁移

时间:2012-08-27 14:35:06

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

我查看了.NET Migrations Engine上的所有选项,发现使用Rails风格迁移的引擎最有趣,主要是因为它们是以数据库无关的方式编写的,可以很容易地使用针对不同的数据库平台。

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

情景

  1. 功能1正在branch1上开发,并将一列添加到名为column1
  2. 的表中
  3. 功能2正在branch2上开发,并将一列添加到名为column2
  4. 的同一个表中
  5. 发布1.1版包含功能2,但功能1尚未完成
  6. 功能1已完成并合并到主干
  7. 发布了1.2版本,但是进入主干的新column1字段是版本1(直接在代码中绑定到版本1.1),因此在迁移时不会在数据库中更新
  8. 使用诸如Migrator.NET之类的工具,问题似乎是迁移版本与实际软件版本有关,而不是SCC提交。但是,必须将该属性添加到源代码管理中的代码中。我已经看到了使用日期而不是版本的示例,但这似乎不能解决手头的问题,只不过是增量版本。

    最接近我发现的答案是在Liquibase FAQ page上,但是在.NET中的Rails风格框架的情况下解决方案需要更改代码(即使在Rik Migrations中,这构成了类似于liquibase changelog文件的属性):

      

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

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

    如果它有任何区别,我使用Git进行源代码控制。注意我已经看到了名为Database migrations in a complex branching system的帖子,但它并没有真正提供答案。

1 个答案:

答案 0 :(得分:1)

我已经考虑过这个问题了,这就是我到目前为止所提出的。我还没有决定迁移框架,但是下面的方法假定使用属性的Migrator.NET之类的东西。但是,这也可以适应其他移民。

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

  1. 当MigrationAttributes的版本高于CI过程中运行的当前数据库版本时,创建单元测试失败
  2. 创建一个单元测试,当对与CI过程中运行的当前数据库版本相同或更低的任何迁移进行更改时,该单元测试失败
  3. 在CI构建之前添加一个步骤,该步骤将查找从Migration类继承的所有类,并添加版本高于当前数据库版本的MigrationAttribute。这可确保迁移在CI过程中成功运行。确保在此步骤之前运行步骤1和2中的单元测试。
  4. 在CI构建之后添加一个步骤,将数据库表中的当前数据库版本设置回当前发布的数据库版本。我们的CI流程数据库版本控制只是暂时的。
  5. 在发布版本之前添加一个步骤,该步骤将查找从Migration类继承的所有类,并添加版本高于当前数据库版本的MigrationAttribute。将此代码更改回主干。
  6. 这里的共同前提是所有这些都可以完全自动化,并且数据库迁移版本属性作为临时CI构建步骤和发布步骤(通过构建过程而非手动)添加。单元测试确保在编辑迁移或在开发周期中过早对其进行版本控制时不会做出任何欺骗行为。

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

    <强>版本

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

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

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

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

    <强>摘要

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

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

    我在实践中没有对此进行测试,但如果我找不到其他解决方案,这可能就是我要去的方向。