使用 ORM (DevExpress XPO,NHibernate或MS Entity Framework)升级数据库的最佳做法是什么?
我正在开始一个新项目,必须选择一个 ORM 。开发过程需要经常发布中间测试版本,并且每个版本可能会在数据库结构中发生更改。每个新版本都必须轻轻升级数据库以保持当前数据。
对于旧解决方案,我将提供一组SQL脚本,用于将数据库从 v1 升级到 v2 ,从 v2 升级到 v3 等,并按顺序执行。
但是如何为 ORM 工作?我还应该编写SQL脚本来升级数据库吗?
我理解简单添加新字段不会导致问题(例如,请参阅XP {的UpdateSchema() method),但是如果我必须拆分表并将当前记录重新分配到2个新表中呢?
答案 0 :(得分:6)
我无法对其他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<MyEntity>()
和foreach
。)
在你将一个表分成两个的更极端的例子中,你可以使用相同的方法,但你可以覆盖UpdateDatabaseBeforeUpdateSchema()
,运行SQL来拆分表,让XPO执行任何其他模式更新,如有必要,请填充UpdateDatabaseAfterUpdateSchema()
。
您会发现遇到约束问题,例如外键违规,因此您可能会发现需要编写一些常规例程,例如DropAllForeignKeyConstraints()
作为UpdateDatabaseBeforeUpdateSchema()
的一部分。有时您会发现XPO已经提供了某些东西,有时却没有。缺少约束和索引将在架构更新中重新生成。 (根据我的经验,切换主数据表的主键是最难的更新例程,以便做对。)
默认情况下,调用都发生在SQL事务中,所以如果有任何失败,它应该全部回滚。
开发人员需要了解域模型的更改何时可能导致底层架构出现问题。
为了进行测试,我们保留了一些旧的客户数据库,并在构建过程中运行一系列前后测试,以确保现有客户能够正确升级他们正在升级的任何版本。在生产中,每当遇到问题升级时,问题数据都会添加到此测试库中,以防止将来出现类似问题。
我们正在与主要的国际公司和银行打交道。客户对结果非常满意。在公司的DBA需要签署更改的情况下,他们似乎不介意使用命令行工具来执行升级而不是脚本。
答案 1 :(得分:0)
大多数迁移解决方案可以处理简单的任务,例如添加新列,关系或删除一个,但在重命名列时无法工作(是添加?还是删除后添加等于重命名?你应该怎么做?在那种情况下处理数据?)
这三个解决方案都有基本的迁移支持,XPO甚至允许您将自己的脚本作为流程的一部分运行(插入静态/测试/传输数据等)。
您还可以使用MigratorDotNet项目,而不是依赖任何有关迁移的ORM特定功能。
就个人而言,我只会在开发/测试环境中使用自动迁移,并且在客户端特定数据库上运行时会提供全套升级脚本,以便从v1升级到v2。
答案 2 :(得分:0)
ORM如何运作?我还应该编写SQL脚本吗? 升级数据库?
这个问题的明确答案应该是程序员的stackexchange线程 - What are the criteria for evaluating an ORM for.NET?,在我用Entity框架和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
答案 3 :(得分:0)
如果您问 - 使用ORM升级数据库的最佳做法是什么 - 我的答案是:如果您的应用程序不仅仅是一个业余爱好者应用程序,请不要使用它。
在很多情况下,许多ORM无法为您的特定数据库需求提供支持,例如:在创建存储过程,创建索引和视图甚至索引视图/物化表而无需编写sql脚本。在ORM-Migration-Code中比在编写SQL脚本时更难解决诸如向现有表添加新的非可空列等问题。
像Visual Studio Data Tools这样的当前工具可以更好地处理这类问题。