【问题标题】:DevExpress XPO vs NHibernate vs Entity Framework: database upgrading issueDevExpress XPO vs NHibernate vs Entity Framework:数据库升级问题
【发布时间】:2015-11-16 17:53:55
【问题描述】:

使用ORMDevExpress XPONHibernateMS Entity Framework)升级数据库的最佳做法是什么?

我正在开始一个新项目并且必须选择一个ORM。开发过程需要经常发布中间测试版本,并且每个版本都可能在数据库结构中发生变化。每个新版本都必须轻轻升级数据库以保留当前数据。

对于旧的解决方案,我会提供一组 SQL 脚本,用于将数据库从 v1 升级到 v2,从 v2 升级到 v3 等并按顺序执行。

但是 ORM 是如何工作的呢?我还应该编写 SQL 脚本来升级数据库吗?

我知道简单地添加新字段不会导致问题(例如,请参阅 UpdateSchema() method 了解 XPO),但如果我必须拆分表并将当前记录重新分配到 2 个新表中怎么办?

【问题讨论】:

标签: entity-framework nhibernate devexpress upgrade xpo


【解决方案1】:

我无法对其他 ORM 发表评论,但自 2007 年以来,我一直将 DevExpress XPO 用于公司财务应用程序。每个版本的架构都会发生一些变化,但多年来也有一些重大的架构变化。默认 XPO 升级机制的某种扩展版本已轻松满足所有更改。

关于升级 XPO 应用程序的基本信息here

  • DevExpress 提供了一个 DBUpdater 工具来帮助您完成升级生产环境的任务。您可以扩展此工具以满足其他要求。在我的应用程序中,我们添加了一些日志记录、回滚预览等选项。

  • 每个模块都有虚拟的UpdateDatabaseBeforeSchemaUpdate()UpdateDatabaseAfterSchemaUpdate() 方法。您可以在其中显着控制升级过程。

正如您所提到的,某些升级将由 XPO 自动处理(例如,添加新列),但有些事情需要额外的控制,例如使用现有记录的默认值初始化新列。

例如,假设 MyNewField 已添加到您的应用程序 2.0 版中的 MyEntity XPO 类中。假设它应该默认为现有记录的值 3。 XPO 将处理新列的创建,但现有记录将为 NULL。 (如果您在 XPO 类中指定默认值,它将只与新记录有关)。为了更正现有记录的值,您可以将以下内容添加到实体模块的覆盖UpdateDatabaseAfterSchemaUpdate()

public override void UpdateDatabaseAfterUpdateSchema()
{
    base.UpdateDatabaseAfterUpdateSchema();
    if (CurrentDBVersion < new Version(2, 0, 0, 0))
        ObjectSpace.GetSession().ExecuteNonQuery(
            "UPDATE [MyEntity] SET [MyNewField] = 3 WHERE [MyNewField] IS NULL");
}

(如果您不想直接使用 SQL,也可以使用 ObjectSpace.GetObjects&lt;MyEntity&gt;()foreach。)

在您将表一分为二的更极端示例中,您可以使用相同的方法,但您将覆盖 UpdateDatabaseBeforeUpdateSchema(),运行 SQL 来拆分表,让 XPO 执行任何其他架构更新,并在必要时, 填充 UpdateDatabaseAfterUpdateSchema() 中的任何默认值。

您会发现遇到约束问题,例如外键违规,因此您可能会发现需要编写一些通用例程,例如 DropAllForeignKeyConstraints() 作为 UpdateDatabaseBeforeUpdateSchema() 的一部分。有时您会发现 XPO 已经提供了一些东西,有时却没有。缺少的约束和索引将在模式更新中重新生成。 (根据我的经验,切换主数据表的主键是最难正确更新的例程。)

默认情况下,所有调用都发生在 SQL 事务中,因此如果任何失败都应该回滚。

开发人员需要注意对域模型的更改何时可能导致底层架构出现问题。

为了进行测试,我们保留了一些旧的客户数据库,并在构建过程中运行了一系列前后测试,以确保现有客户能够正确升级他们正在升级的任何版本。在生产中,每当我们遇到升级问题时,都会将问题数据添加到此测试库中,以防止将来出现类似问题。

我们正在与主要的国际公司和银行打交道。客户对结果非常满意。在公司的 DBA 需要签署更改的情况下,他们似乎不介意使用命令行工具而不是脚本来进行升级。

【讨论】:

  • 您所描述的内容与 XAF 有关,而不是专门针对 XPO。
【解决方案2】:

大多数迁移解决方案可以处理简单的任务,例如添加新列、关系或删除一个,但在重命名列时无法工作(这是添加?还是添加后的删除等于重命名?你应该怎么做?在那种情况下如何处理数据?)

所有三个解决方案都支持基本的迁移,XPO 甚至允许您运行自己的脚本作为过程的一部分(插入静态/测试/持续数据等)

您还可以使用MigratorDotNet 项目,而无需依赖任何有关迁移的 ORM 特定功能。

就我个人而言,我只会在开发/测试环境中使用自动迁移,并且在客户端特定数据库上运行时会拥有全套升级脚本,例如从 v1 升级到 v2。

【讨论】:

  • 感谢您的快速响应。我使用Apex SQL Tools 生成用于升级的SQL 脚本。但我担心的是用于升级的 SQL 脚本会破坏 ORM 与数据库类型的独立性。
  • 但是记住 ORM 只是为了解决另一个问题,即从/向数据库读取。升级架构只是另一个问题,最好由其他工具处理,无论是 Migrator.NET 还是 Apex SQL 工具等外部工具。
【解决方案3】:

ORM 将如何工作?我还应该编写 SQL 脚本吗? 升级数据库?

这个问题的明确答案应该在 Programmer 的 stackexchange 线程 - What are the criteria for evaluating an ORM for.NET? 上,对于你提出的问题,我得到了简单的答案,并且与我在使用实体框架和 Code smith ORM 模板开发一些项目时的 ORM 经验相匹配。

ORM 如何管理数据模型中的更改?如果我必须拆分一个表并将当前记录重新分配到 2 个新表中怎么办?

有些可以在一定的范围内自动更新数据库,其他的 什么都不做,你必须自己做肮脏的工作;其他 提供处理更改的框架,让您控制数据库 更新。 That means every couple of days 有人需要花一个小时更新模型以添加表或更改正在更改的数据类型

参考:
https://softwareengineering.stackexchange.com/questions/6543/what-are-the-benefits-of-using-database-abstraction-by-orm
https://softwareengineering.stackexchange.com/questions/41739/best-arguments-for-against-introducing-orm-technology-into-a-companies-dev-proce/41833#41833

【讨论】:

    【解决方案4】:

    如果您问 - 使用 ORM 升级数据库的最佳做法是什么 - 我的回答是:如果您的应用程序不仅仅是一个爱好者应用程序,请不要使用它。

    在很多情况下,许多 ORM 无法为您的特定数据库需求提供支持,例如在创建存储过程时,无需编写 sql 脚本即可创建索引和视图甚至索引视图/物化表。在 ORM-Migration-Code 中解决诸如向现有表中添加新的不可为空列之类的问题比编写 SQL 脚本要困难得多。

    Visual Studio Data Tools 等当前工具确实可以更好地处理这类问题。

    【讨论】:

      猜你喜欢
      • 2011-11-06
      • 1970-01-01
      • 1970-01-01
      • 2011-02-21
      • 2021-03-08
      • 1970-01-01
      • 2011-03-19
      • 2011-07-07
      • 1970-01-01
      相关资源
      最近更新 更多