我无法对其他 ORM 发表评论,但自 2007 年以来,我一直将 DevExpress XPO 用于公司财务应用程序。每个版本的架构都会发生一些变化,但多年来也有一些重大的架构变化。默认 XPO 升级机制的某种扩展版本已轻松满足所有更改。
关于升级 XPO 应用程序的基本信息here。
正如您所提到的,某些升级将由 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<MyEntity>() 和 foreach。)
在您将表一分为二的更极端示例中,您可以使用相同的方法,但您将覆盖 UpdateDatabaseBeforeUpdateSchema(),运行 SQL 来拆分表,让 XPO 执行任何其他架构更新,并在必要时, 填充 UpdateDatabaseAfterUpdateSchema() 中的任何默认值。
您会发现遇到约束问题,例如外键违规,因此您可能会发现需要编写一些通用例程,例如 DropAllForeignKeyConstraints() 作为 UpdateDatabaseBeforeUpdateSchema() 的一部分。有时您会发现 XPO 已经提供了一些东西,有时却没有。缺少的约束和索引将在模式更新中重新生成。 (根据我的经验,切换主数据表的主键是最难正确更新的例程。)
默认情况下,所有调用都发生在 SQL 事务中,因此如果任何失败都应该回滚。
开发人员需要注意对域模型的更改何时可能导致底层架构出现问题。
为了进行测试,我们保留了一些旧的客户数据库,并在构建过程中运行了一系列前后测试,以确保现有客户能够正确升级他们正在升级的任何版本。在生产中,每当我们遇到升级问题时,都会将问题数据添加到此测试库中,以防止将来出现类似问题。
我们正在与主要的国际公司和银行打交道。客户对结果非常满意。在公司的 DBA 需要签署更改的情况下,他们似乎不介意使用命令行工具而不是脚本来进行升级。