遗留数据库上的 NHibernate

Posted

技术标签:

【中文标题】遗留数据库上的 NHibernate【英文标题】:NHibernate on legacy DB 【发布时间】:2009-01-26 21:19:59 【问题描述】:

我很惭愧,但我不得不说。我没有使用过ORM。我真的在考虑 NHibernate,因为它似乎是最成熟的 .Net 产品(如果我错了,请纠正我)。现在,问题是我们有一个以 SqlServer 作为主要集成点的大型电子商务/预订系统,在存储过程中包含相当多的业务逻辑。现在 - 显然 - 这种架构是我们想要摆脱的东西,我们已经这样做了一段时间,一点一点。所以,我真正的问题是,开始使用 NHibernate 来开发新功能而不是回过头来映射所有遗留的东西有多可行?这种逐步引入并支持ORM,如果支持,你会推荐吗?

【问题讨论】:

您目前使用什么作为 DAL? 大部分遗留代码只使用 ADO.Net,传递数据集和表。使用 TDD 编写的新代码大多使用存储库模式和手动映射的变体。 【参考方案1】:

如果您使用的是遗留数据库,您会发现 ORM 工具相当难以使​​用、配置、维护和优化。当我们使用 NHibernate 将我们的域模型映射到现有数据库时,我们遇到了许多问题。其中一些是:

    模型对象很难映射到现有的表(我们有超过 100 个表),NHibernate 的一些要求非常突出,例如每个表都必须有一个 ID 字段才能映射到域对象.此外,映射多对多关系也很难掌握和使用。

    保持大容量 映射需要映射到的 XML 遗留数据库成为全职 开发人员的工作,相当 具有挑战性,特别是在一个团队中 10 多名开发人员。

    随着复杂性的增加,我们的查询性能下降,因为数据模型和对象模型并不总是与业务匹配,需要不断调整。必须编写大量数据聚合代码。例如,如果我们需要显示一个连接多个表的网格,我们过去必须加载多个域对象,将它们放在一起并在一个网格中显示。该代码很难维护和调试。

    此外,有时我们必须运行匿名查询,即我们只需要某些对象的一些属性,而不是整个对象。这真的很难编写、维护甚至实现,并且违背了 ORM 范式,但我们别无选择,只能这样做。

    我们遇到的另一个问题是数据库在不断变化,因为 DBA 会重构表,这总是会破坏我们的域对象。保持模型和表格同步并确保应用程序仍然正常工作是一项练习。

长话短说...我们了解到,如果有一种方法可以将业务所需的 SQL 直接映射到我们的 UI 模型或域对象而无需担心配置,那将是一个更好的解决方案。

在经历了这些经验之后,我们开发了 Orasis Mapping Studio。它是一种专门设计用于处理遗留数据库以及现有 .NET 模型/域对象的映射工具。它接受您的 SQL 查询,并允许您通过以图形方式显示查询和对象的元数据并使用拖放创建对象属性和查询列之间的映射,将它们映射到现有的 .NET 对象。该工具会自动生成执行映射以读取对象所需的所有 ADO.NET 代码。然后,您可以在 DAL 层中使用生成的代码或使用生成的程序集来检索和保存数据。

您可以在这里尝试:Orasis Mapping Studio。它是我们认为开发人员真正需要的工具,特别是用于处理遗留数据库以及性能是关键要求的地方。它是由开发人员为开发人员编写的,因此它处理了一些复杂的细节,例如对象继承、嵌套对象、数据类型转换等。祝你好运!

【讨论】:

唉,你的网站现在看起来很糟糕。【参考方案2】:

这将取决于您当前数据库的“NHibernate 友好”程度。 NHibernate 喜欢单列主键(如果它们都被命名为“id”就更好了)。据我所知,大多数 ORM 对存储过程都不是很友好。您是否考虑过如何定义传输对象以从数据库中来回获取数据?

顺便说一句,没有什么好羞愧的。 ORM 是个好东西,但你试图找到最好的方法是对的。

【讨论】:

我想这个问题不可能有“正确”的答案,但我将其标记为答案,因为它非常简洁。【参考方案3】:

我没有亲自这样做,但是您可以将命名查询中的存储过程复制粘贴到映射文件中,然后再将它们一一删除。

如果您对 ORM 没有任何经验,可能很难在大型遗留项目中开始学习它,因为您必须发现 ORM 的所有非标准特性,而这些特性不会在新建项目中使用,或一年只使用一次。 NHibernate 有很多选项来支持遗留数据库。

当您准备好跨越学习曲线并有足够的勇气开始使用新技术时,您可以从 NHibernate 开始,但是如果您想逐步学习新技术,我会等到您开始使用 NHibernate 后再开始新的技术绿地项目。

【讨论】:

我明白你的意思,但我的想法(虽然可能没有很好地表达)是我们可以开始将它用于在遗留数据库上工作的新功能。因此,新功能将是“精心设计”的,只是我们不会触及旧代码。 在 NHibernate 的缓存系统中使用相同数据库表的新旧功能可能很难分开。【参考方案4】:

任何体面的 ORM 工具都应该支持渐进式集成。这里的技巧是在 DAO 级别(数据访问对象层)进行明确的分离。如果您可以通过定义明确的 API 隐藏您的数据访问怪癖,那么您是否使用 ORM 都无关紧要。

话虽如此,ORM 引入的复杂性与表模型的复杂性直接相关。对于同一个表,您可以有许多不同的映射,只需确保您事先进行了一些试验,以了解 ORM 解决方案的怪癖,例如对象缓存、后写查询、代理访问等。 ORM 解决方案的真正好处是使用对象而不是虚拟 POJO 类。这使得对业务进行更改比使用存储过程或平面对象容易得多。

顺便说一句,我参与了一个项目,我们将 sprocs 中的整个应用程序迁移到 java。虽然我们没有使用 sproc,但真正的痛苦是 sprocs 架构没有很好地定义,很多 sprocs 调用其他 sprocs 使得一次只迁移一些 sprocs 非常困难。

【讨论】:

【参考方案5】:

NHibernate 中没有任何东西会限制你这样做。在某些时候,您可能希望将旧代码转换为也使用 NHibernate,因为在您可以导航所有对象之间的关系之前,您不会看到 ORM 的全部好处。

最大的挑战可能是让您的旧表结构适应 NHibernate 的单表每类方法。有一些方法可以解决这个问题,但这可能很棘手。不过,我认为这是值得的。

【讨论】:

使用 NHibernate,您不需要为每个班级创建一个表格。 我发现每个班级有多个表格很痛苦。例如:建立一个继承层次结构,其中鉴别器不在主表上。遗留数据库由于其怪癖而需要更长的时间来映射。【参考方案6】:

您曾提到您正在摆脱当前的架构,但您是否需要坚持您的旧数据库设计(例如,DBA 严格负责设计和维护它)或者您当前的数据库设计是否正在重构(考虑到也适用于 O/R 映射器)?

如果难以摆脱当前的遗留设计,您可能会考虑使用普通的旧 T-SQL 查询,而不是更少- 灵活的 Hibernate 样式 XML/属性来映射数据。

根据您希望如何进行设计,您可以通过使用您自己的抽象 DAO 工厂或 iBATIS DataAccess API 透明地并排使用 iBATIS SqlMap 和 NHibernate ,并且仍然与 NHibernate 兼容。)

【讨论】:

数据库设计正在重构中,有一些核心表真的很难重构,很可能会在很长一段时间内保持不变。【参考方案7】:

我同意 Ahmad 的说法,我过去也遇到过类似的问题。我遇到的大部分麻烦不是来自技术本身,而是来自开发人员的采用,改用 NHibernate 意味着工作习惯的改变,至少可以说,这并不总是那么容易。

如果您是 ORM 的新手,使用它开始一个全新的项目可能比尝试转换旧项目更好。

我建议将遗留项目转换为 ORM 是尝试使用某种生成工具,如 LLBGen 或 .netTiers 甚至 Linq2SQL。这样一来,您就可以更轻松地使用 ORM,而无需 NHibernate 可能强加的创伤性重写。

【讨论】:

【参考方案8】:

为什么存储过程“明显”不好?存储过程中的业务逻辑是否会造成痛苦?

Microsoft 似乎有许多可用的持久性技术(例如 LINQ)。我不知道如何评估它们与 NHibernate,但我不会推荐 ORM,除非你有非常好的对象可以映射到。

【讨论】:

存储过程中的业务逻辑在某些时候会引起痛苦,这只是生活中的事实。 sprocs 中的业务逻辑 - 对我来说 - 显然很糟糕,原因有很多。更难测试和更难版本是两个最明显的。此外,业务逻辑本身更难在 T-Sql 中表达,因此更难维护。 LINQ 如何成为一种持久性技术? 但这是一个宗教论点 - 数据人员会认为这是一个放置逻辑的好地方,因为所有共享数据库的应用程序都会获取一次逻辑。只有对象偏执者(如我)坚持认为这总是不好的。我只是保持开放的心态。 我听到你的声音,我认为你的问题很有效(我不会反对你),我只是在回答你为什么认为它在我们的案例中“显然”不好。在任何情况下,我都没有说这显然很糟糕。至少那不是我的本意。

以上是关于遗留数据库上的 NHibernate的主要内容,如果未能解决你的问题,请参考以下文章

华为培训遗留解决知识点

译遗留浏览器中的表单

多个端口上的 pgBouncer?

Python 遗留伯克利数据库

数据库中的功能测试和遗留代码

将附加要求纳入遗留数据库设计