113

在我的学徒期间,我将NHibernate用于一些较小的项目,这些项目主要是我自己编码和设计的。现在,在开始一些更大的项目之前,讨论了如何设计数据访问以及是否使用 ORM 层。由于我仍处于学徒阶段,并且仍然认为自己是企业编程的初学者,因此我并没有真正尝试提出自己的观点,即使用对象关系映射器到数据库可以大大简化开发。开发团队的其他编码人员比我更有经验,所以我想我会照他们说的做。:-)

但是,我不完全理解不使用 NHibernate 或类似项目的两个主要原因:

  1. 可以使用 SQL 查询构建自己的数据访问对象,然后将这些查询复制到 Microsoft SQL Server Management Studio 之外。
  2. 调试 ORM 可能很困难。

所以,当然我可以用很多SELECTs 等来构建我的数据访问层,但是在这里我错过了自动连接、延迟加载代理类以及如果表获得新列或列获得的维护工作量较低的优势重命名。(更新大量SELECT,INSERTUPDATE查询与更新映射配置并可能重构业务类和 DTO。)

此外,如果您不太了解该框架,使用 NHibernate 可能会遇到无法预料的问题。例如,这可能是信任 Table.hbm.xml,您在其中设置了要自动验证的字符串长度。但是,我也可以想象一个“简单”的基于 SqlConnection 查询的数据访问层中的类似错误。

最后,上面提到的那些论点真的是一个很好的理由不将 ORM 用于基于数据库的非平凡的企业应用程序吗?他们/我可能错过了其他论点吗?

(我可能应该补充一点,我认为这就像第一个需要团队合作的基于 .NET/C# 的“大型”应用程序。在 Stack Overflow 上被视为非常正常的良好实践,例如单元测试或持续集成,是非- 到现在为止。)

4

20 回答 20

64

简短的回答是肯定的,确实有充分的理由。事实上,在某些情况下您不能使用 ORM。

举个例子,我在一家大型企业金融机构工作,我们必须遵循很多安全准则。为了满足对我们施加的规则和规定,通过审核的唯一方法是将数据访问保持在存储过程中。现在有些人可能会说这简直是愚蠢的,但老实说并非如此。使用 ORM 工具意味着工具/开发人员可以插入、选择、更新或删除他或她想要的任何内容。存储过程提供了更多的安全性,尤其是在处理客户端数据的环境中。我认为这是考虑的最大原因。安全。

于 2008-10-11T15:12:16.753 回答
59

ORM 的最佳选择

ORM 对于自动化 95% 以上的查询非常有用。它们的特殊优势在于您拥有一个具有强大对象模型架构的应用程序和一个可以很好地与该对象模型配合使用的数据库。如果你正在做一个新的构建并且你的团队有很强的建模技能,那么你可能会用 ORM 获得很好的结果。

您可能有一些最好手动完成的查询。在这种情况下,不要害怕编写一些存储过程来处理这个问题。即使您打算跨多个 DBMS 平台移植您的应用程序,依赖于数据库的代码也将是少数。请记住,您将需要在您打算支持它的任何平台上测试您的应用程序,一些存储过程的一些额外移植工作不会对您的 TCO 产生太大影响。对于第一个近似值,98% 的可移植性与 100% 的可移植性一样好,并且远远优于绕过 ORM 限制的复杂或性能不佳的解决方案。

我已经看到前一种方法在一个非常大的(100 个员工年)J2EE 项目中运行良好。

ORM 可能不是最适合的地方

在其他情况下,可能存在比 ORM 更适合应用程序的方法。Fowler 的企业应用程序架构模式有一节关于数据访问模式,它很好地对各种方法进行了分类。我见过的一些 ORM 可能不适用的例子是:

  • 在具有大量存储过程遗留代码库的应用程序上,您可能希望使用面向功能的(不要与函数式语言混淆)数据访问层来包装现有的存储过程。这重用了现有(因此经过测试和调试)的数据访问层和数据库设计,这通常代表着相当大的开发和测试工作,并且不必将数据迁移到新的数据库模型。这通常是一种很好的方法,将 Java 层包裹在遗留的 PL/SQL 代码库中,或者使用 Web 界面重新定位富客户端 VB、Powerbuilder 或 Delphi 应用程序。

  • 变体是您继承不一定非常适合 OR 映射的数据模型。如果(例如)您正在编写一个从外部接口填充或提取数据的接口,那么您最好直接使用数据库。

  • 跨系统数据完整性很重要的金融应用程序或其他类型的系统,尤其是当您使用具有两阶段提交的复杂分布式事务时。您可能需要比 ORM 能够支持的更好地微观管理您的事务。

  • 您想要真正调整数据库访问的高性能应用程序。在这种情况下,最好在较低级别工作。

  • 在您使用现有数据访问机制(如 ADO.Net)的情况下,它“足够好”并且可以很好地使用该平台,这比 ORM 带来的好处更大。

  • 有时数据只是数据 - 可能是(例如)您的应用程序正在使用“事务”而不是“对象”,这是域的明智视图。这方面的一个例子可能是一个财务包,其中您有带有可配置分析字段的交易。虽然应用程序本身可能构建在 OO 平台上,但它并不依赖于单个业务域模型,并且可能不知道的不仅仅是 GL 代码、帐户、文档类型和六个分析字段。在这种情况下,应用程序不知道业务领域模型本身,并且对象模型(超出分类帐结构本身)与应用程序无关。

于 2010-07-07T15:29:15.187 回答
38

首先 - 使用 ORM 不会使您的代码更容易测试,也不一定会在持续集成场景中提供任何优势。

根据我的经验,虽然使用 ORM 可以提高开发速度,但您需要解决的最大问题是:

  1. 测试你的代码
  2. 维护你的代码

这些问题的解决方案是:

  1. 使您的代码可测试(使用SOLID原则)
  2. 为尽可能多的代码编写自动化测试
  3. 尽可能频繁地运行自动化测试

谈到您的问题,您列出的两个反对意见似乎更像是无知而不是其他任何东西。

无法手动编写 SELECT 查询(我想这就是需要复制粘贴的原因)似乎表明迫切需要一些 SQL 培训。

我不使用 ORM 的原因有两个:

  1. 公司政策严禁(这种情况下我会去其他地方工作)
  2. 该项目是数据密集型的,使用供应商特定的解决方案(如 BulkInsert)更有意义。

通常对 ORM(尤其是 NHibernate)的拒绝是:

  1. 速度

    没有理由使用 ORM 会比手动编码的数据访问慢。事实上,由于内置了缓存和优化,它可以更快。一个好的 ORM 将生成一组可重复的查询,您可以针对这些查询优化您的架构。一个好的 ORM 还将允许使用各种获取策略有效地检索相关数据。

  2. 复杂

    关于复杂性,使用 ORM 意味着更少的代码,这通常意味着更少的复杂性。许多使用手写(或代码生成)数据访问的人发现自己在“低级”数据访问库上编写自己的框架(例如为 ADO.Net 编写辅助方法)。这些等同于更复杂,更糟糕的是,它们很少有很好的文档记录或经过很好的测试。
    如果您专门研究 NHibernate,那么 Fluent NHibernate 和 Linq To NHibernate 等工具也可以缓和学习曲线。

让我对整个 ORM 辩论感到震惊的是,那些声称使用 ORM 会太难/太慢/无论如何的人,正是那些非常乐意使用 Linq To Sql 或 Typed Datasets 的人。虽然 Linq To Sql 是朝着正确方向迈出的一大步,但它仍然落后于一些开源 ORM 的光年。但是,Typed Datasets 和 Linq To Sql 的框架仍然非常复杂,并且使用它们来超越 (Table=Class) + (basic CRUD) 是非常困难的。

我的建议是,如果在一天结束时,您无法获得 ORM,那么请确保您的数据访问与其他代码分开,并且您遵循四人组的编码建议一个界面。另外,获取一个依赖注入框架来进行连接。

(咆哮怎么样?)

于 2008-10-17T17:36:34.167 回答
35

对于许多常见问题,像 Hibernate 这样的 ORM 工具是天赐之物,而在少数情况下它是一个障碍。我对你的项目了解得不够多,不知道它是什么。

Hibernate 的优势之一是您只能说 3 次:在类、.hbm.xml 文件和数据库中提到每个属性。使用 SQL 查询,您的属性位于类、数据库、选择语句、插入语句、更新语句、删除语句以及支持 SQL 查询的所有编组和解组代码中!这可能会很快变得混乱。另一方面,你知道它是如何工作的。你可以调试它。这一切都在您自己的持久层中,而不是埋在第 3 方工具的内部。

Hibernate 可能是 Spolsky 的泄漏抽象定律的典型代表。稍微偏离常规,您需要了解该工具的深层内部工作原理。当您知道您可以在几分钟内修复 SQL 时,这可能会非常烦人,但是您却花费数小时试图诱使您的 dang 工具生成合理的 SQL。调试有时是一场噩梦,但很难说服没有去过那里的人。

编辑:如果他们不想改变 NHibernate 并且他们想要控制他们的 SQL 查询,你可能想要研究 iBatis.NET。

编辑 2:不过,这是一个大红旗:“到目前为止,在 Stack Overflow 上被视为非常正常的良好做法,例如单元测试或持续集成,在这里都不存在。” 那么,这些“经验丰富”的开发者,他们在开发过程中有哪些经验呢?他们的工作保障?听起来您可能属于对该领域并不特别感兴趣的人,所以不要让他们扼杀您的兴趣。你需要保持平衡。投入了战斗。

于 2008-10-11T15:29:47.327 回答
28

近年来,ORM 出现了爆炸式增长,您更有经验的同事可能仍在思考“每个数据库调用都应该通过存储过程”的心态。

为什么 ORM 会让事情变得更难调试?无论是来自存储过程还是来自 ORM,您都会得到相同的结果。

我想我能想到的唯一真正的 ORM 缺点是安全模型不太灵活。

编辑:我刚刚重新阅读了您的问题,看起来他们正在将查询复制并粘贴到内联 sql 中。这使得安全模型与 ORM 相同,因此与 ORM 相比,这种方法绝对没有优势。如果他们使用未参数化的查询,那么这实际上是一个安全风险。

于 2008-10-11T14:55:33.450 回答
13

我在一个不使用 ORM 的项目上非常成功。这是一个项目

  1. 从一开始就必须是水平缩放的
  2. 必须快速开发
  3. 有一个相对简单的领域模型

让 NHibernate 在水平分区结构中工作所花费的时间比开发一个了解我们的分区方案的超级简单数据映射器所花费的时间要长得多......

因此,在我从事的 90% 的 ORM 项目中,它都提供了宝贵的帮助。但是在一些非常具体的情况下,我认为不使用 ORM 是最好的。

于 2008-10-11T15:14:06.813 回答
11

首先让我说,如果正确集成,ORM 可以使您的开发生活更轻松,但是在一些问题中,ORM 实际上会阻止您实现既定的要求和目标。

我发现,在设计对性能要求很高的系统时,我经常面临着寻找提高系统性能的方法的挑战。很多时候,我最终得到的解决方案具有高写入性能配置文件(这意味着我们写入数据的次数远远多于读取数据的次数)。在这些情况下,我想利用数据库平台为我提供的设施来达到我们的性能目标(它是 OLTP,而不是 OLAP)。因此,如果我使用 SQL Server 并且我知道我有很多数据要写入,我为什么不使用批量插入...好吧,正如您可能已经发现的那样,大多数 ORMS(我不知道是否即使是一个也没有)没有能力利用平台特定的优势,如批量插入。

您应该知道您可以混合使用 ORM 和非 ORM 技术。我刚刚发现有少数 ORM 无法支持您的要求的边缘情况,您必须针对这些情况解决它们。

于 2008-10-11T15:46:51.287 回答
11

对于一个重要的基于数据库的企业应用程序,确实没有理由不使用 ORM。

除了特点:

  • 通过不使用 ORM,您正在解决一个已经被拥有大量资源的大型社区或公司反复解决的问题。
  • 通过使用 ORM,您的数据访问层的核心部分可以从该社区或公司的调试工作中受益。

为了在争论中提出一些观点,请考虑使用 ADO.NET 与编写代码自己解析表格数据流的优势。

我已经看到对如何使用 ORM 的无知证明开发人员对 ORM 的蔑视是正当的,例如:急切加载(我注意到你没有提到)。想象一下,您想要检索一个客户和他们的所有订单,以及所有这些订单详细信息项目。如果您只依赖延迟加载,您将离开您的 ORM 体验,并认为:“ORM 很慢”。如果你学会了如何使用急切加载,你将在 2 分钟内用 5 行代码完成,而你的同事将需要半天时间来实现:对数据库进行一次查询并将结果绑定到对象层次结构。另一个例子是手动编写 SQL 查询来实现分页的痛苦。

使用 ORM 的可能例外情况是,如果该应用程序是一个 ORM 框架,旨在应用专门的业务逻辑抽象,并且旨在在多个项目中重用。但是,即使是这种情况,您也可以通过使用这些抽象增强现有 ORM 来更快地采用。

不要让您的高级团队成员的经验将您拖向计算机科学发展的相反方向。我在专业上发展了 23 年,其中一个不变的就是老派对新的不屑一顾。ORM 之于 SQL 就像 C 语言之于汇编一样,您可以打赌,C++ 和 C# 的等价物正在开发中。一行新式代码等于 20 行旧式代码。

于 2012-10-17T04:05:13.580 回答
9

当您需要更新 50000000 条记录时。设置一个标志或其他任何东西。

尝试使用 ORM 执行此操作,而不调用存储过程或本机 SQL 命令。

更新 1:也尝试检索仅包含少数字段的记录。(当你有一个非常“宽”的桌子时)。或标量结果。ORM 在这方面也很烂。

更新 2:似乎 EF 5.0 beta 承诺批量更新,但这是非常热门的新闻(2012 年 1 月)

于 2010-10-26T21:30:39.050 回答
8

我认为也许当您在更大的系统上工作时,您可以使用 CodeSmith 之类的代码生成器工具而不是 ORM... 我最近发现了这个:Cooperator Framework,它生成 SQL Server 存储过程并生成您的业务实体、映射器、网关, lazyload 和 C# 中的所有内容...检查一下...它是由阿根廷的一个团队编写的...

我认为它介于编码整个数据访问层和使用 ORM 之间......

于 2008-10-16T03:36:42.193 回答
6

就个人而言,我(直到最近)反对使用 ORM,并且习惯于编写一个封装所有 SQL 命令的数据访问层。对 ORM 的主要反对意见是我不相信 ORM 实现可以编写完全正确的 SQL。而且,从我曾经看到的 ORM(主要是 PHP 库)来看,我认为我是完全正确的。

现在,我的大部分 Web 开发都使用 Django,我发现包含的 ORM 非常方便,而且由于数据模型首先用他们的术语表示,然后才用 SQL 表示,它确实可以很好地满足我的需求。我相信它不会太难超越它并且需要用手写SQL来补充;但对于 CRUD 访问来说绰绰有余。

我不知道 NHibernate;但我想它对于您需要的大部分内容也“足够好”。但是如果其他编码人员不信任它;它将成为每个与数据相关的错误的主要嫌疑人,使验证更加乏味。

您可以尝试在您的工作场所逐步引入它,首先关注小型“显而易见”的应用程序,例如简单的数据访问。一段时间后,它可能会用在原型上,并且可能不会被替换......

于 2008-10-11T16:09:00.400 回答
5

如果它是一个 OLAP 数据库(例如,用于报告/分析的静态、只读数据等),那么实现 ORM 框架是不合适的。相反,最好使用数据库的本机数据访问功能,例如存储过程。ORM 更适合事务 (OLTP) 系统。

于 2008-12-02T20:32:30.627 回答
5

我认为不使用 ORM 有很多充分的理由。首先,我是一名 .NET 开发人员,我喜欢坚持出色的 .NET 框架已经为我提供的内容。它可以完成我可能需要的一切。通过这样做,您可以使用更标准的方法,因此在同一项目上工作的任何其他开发人员都有更好的机会能够拾取那里的内容并使用它运行。微软已经提供的数据访问能力相当丰富,没有理由放弃它们。

我已经是 10 年的专业开发人员,领导了多个非常成功的数百万美元以上的项目,而且我从未编写过需要能够切换到任何数据库的应用程序。为什么你会希望客户这样做?仔细计划,根据您的需要选择正确的数据库,并坚持下去。就个人而言,SQL Server 已经能够完成我曾经需要做的任何事情。这很简单,而且效果很好。甚至还有支持高达 10GB 数据的免费版本。哦,它与 .NET 配合得非常好。

我最近不得不开始从事几个使用 ORM 作为数据层的项目。我认为这很糟糕,而且我不得不无缘无故地学习如何使用一些额外的东西。在客户确实需要更改数据库的极其罕见的情况下,我可以轻松地在比我花在与 ORM 提供者愚弄上花费的时间更短的时间内重新设计整个数据层。

老实说,我认为 ORM 有一个真正的用途:如果您正在构建像 SAP 这样的应用程序,它确实需要能够在多个数据库上运行。否则,作为解决方案提供商,我会告诉我的客户这个应用程序设计为在这个数据库上运行,就是这样。再一次,经过 10 年和无数次的申请,这从来都不是问题。

否则,我认为 ORM 适合那些不了解少即是多的开发人员,并认为他们在应用程序中使用的 3rd 方工具越酷,他们的应用程序就会越好。我会把这样的事情留给顽固的超级极客,同时我会开发出更多优秀的软件,同时任何开发人员都可以拿起并立即投入使用。

于 2012-01-31T19:31:45.957 回答
4

ORM 有两个方面令人担忧。首先,它们是由其他人编写的代码,有时是封闭源代码,有时是开源代码,但范围很大。其次,他们复制数据。

第一个问题导致两个问题。您正在依赖外部代码。我们都这样做,但选择这样做不应该掉以轻心。如果它不能满足您的需求怎么办?你什么时候会发现这个?你住在你的 ORM 为你绘制的盒子里。

第二个问题是两阶段提交之一。正在将关系数据库复制到对象模型。您更改了对象模型,它应该更新数据库。这是一个两阶段提交,而不是最容易调试的事情。

于 2008-10-11T16:08:54.207 回答
3

运行时性能是我能想到的唯一真正的缺点,但我认为这不仅仅是一个公平的权衡,因为 ORM 为您节省了开发/测试/等时间。在大多数情况下,您应该能够定位数据瓶颈并更改对象结构以提高效率。

我以前没有使用过 Hibernate,但我注意到一些“现成的”ORM 解决方案的一件事是缺乏灵活性。我敢肯定这取决于您选择哪个以及您需要做什么。

于 2008-10-11T15:16:29.490 回答
3

我建议阅读此书以了解 ORM 的缺点。

http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx

就我自己而言,我发现 ORM 对于我编写的大多数应用程序都非常有用!

/阿斯格

于 2009-04-21T19:27:51.853 回答
3

我对 Hibernate 的体验是它的语义很微妙,当出现问题时,很难理解引擎盖下出了什么问题。我从朋友那里听说,通常从 Criteria 开始,然后需要更多的灵活性并需要 HQL,后来注意到毕竟需要原始 SQL(例如,Hibernate 没有联合 AFAIK)。

同样使用 ORM,人们很容易过度使用现有的映射/模型,这导致对象具有许多未初始化的属性。所以在查询之后,内部事务 Hibernate 会进行额外的数据获取,这可能会导致速度变慢。同样可悲的是,休眠模型对象有时会泄漏到视图架构层,然后我们会看到 LazyInitializationExceptions。

要使用 ORM,必须真正了解它。不幸的是,人们很容易给人一种很容易的印象,而事实并非如此。

于 2009-05-20T03:36:40.637 回答
3

本身不是一个答案,我想改写我最近听到的一句话。“一个好的 ORM 就像一只雪人,每个人都在谈论它,但没有人看到它。”

每当我将手放在 ORM 上时,我通常会发现自己在为那个 ORM 的问题/限制而苦苦挣扎。最后,是的,它做了我想要的,它写在那个糟糕的文档中的某个地方,但我发现自己又浪费了一个小时,我永远不会得到。任何使用过 nhibernate,然后在 postgresql 上使用流利的 nhibernate 的人都会明白我的经历。“这段代码不受我控制”的持续感觉真的很糟糕。

我没有指责或说它们很糟糕,但我开始思考我放弃了什么只是为了在一个表达式中自动化 CRUD。现在我认为我应该少用 ORM,也许创建或找到一个至少可以启用数据库操作的解决方案。但这只是我。我相信在这个 ORM 领域有些事情是错误的,但我没有足够的技能来表达它。

于 2011-05-08T21:30:23.910 回答
2

我认为使用 ORM 仍然是一个好主意。特别是考虑到你给出的情况。从您的帖子看来,您在数据库访问策略方面更有经验,我会提出使用 ORM。

#1 没有参数,因为复制和粘贴查询以及文本中的硬编码没有灵活性,而对于 #2,大多数 orm 将包装原始异常,允许跟踪生成的查询等,因此调试也不是火箭科学。

至于验证,在任何内置验证之上,使用 ORM 通常还可以更轻松地开发验证策略。

编写自己的框架可能很费力,而且经常会遗漏一些事情。

编辑:我想再强调一点。如果您的公司采用 ORM 策略,这将进一步提高其价值,因为您将制定使用和实施的指南和实践,每个人都将进一步增强他们对所选框架的了解,从而减轻您提出的问题之一。此外,当情况出现时,您将了解哪些有效,哪些无效,最终将节省大量时间和精力。

于 2008-10-11T15:16:45.467 回答
1

每个 ORM,即使是“好的”,都带有一定数量的假设,这些假设与软件用于在应用程序层和数据存储之间来回传递数据的底层机制相关。

我发现对于中等复杂的应用程序,解决这些假设通常比简单地编写更简单的解决方案(例如:查询数据和手动实例化新实体)花费更多时间。

特别是,当您使用多列键或其他适度复杂的关系时,您可能会遇到问题,这些关系刚好超出您的 ORM 在下载代码时为您提供的方便示例的范围。

我承认对于某些类型的应用程序,特别是那些具有大量数据库表或动态生成的数据库表的应用程序,ORM 的自动魔术过程可能很有用。

否则,ORM 就完蛋了。我现在认为它们基本上是一种时尚。

于 2011-02-18T21:52:22.953 回答