6

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

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

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

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

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

4

4 回答 4

6

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

这里有关于升级 XPO 应用程序的很好的基本信息。

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

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

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

例如,假设MyNewFieldMyEntity在您的应用程序 2.0 版中添加到 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<MyEntity>()and a 。)foreach

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

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

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

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

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

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

于 2012-06-15T11:04:08.870 回答
0

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

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

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

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

于 2012-05-21T04:29:59.660 回答
0

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

这个问题的明确答案应该在程序员的 stackexchange 线程上 -评估 ORM for.NET 的标准是什么?,对于您提出的问题,我得到了简单的答案,并且与我在使用实体框架和 Code smith ORM 模板开发一些项目时使用 ORM 的经验相匹配。

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

有些可以在一定范围内自动更新数据库,有些什么都不做,你必须自己做这些脏活;其他提供了一个处理更改的框架,可以让您控制数据库更新。这意味着每隔几天有人需要花一个小时更新模型以添加表或更改正在更改的数据类型

参考:
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

于 2012-05-21T05:15:40.723 回答
-1

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

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

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

于 2015-11-16T09:53:55.143 回答