Are there good reasons not to use an ORM?

在我的学徒期间,我使用 冬眠的一些较小的项目,我主要是自己编码和设计。现在,在开始一些更大的项目之前,讨论出现了如何设计数据访问以及是否使用 ORM 层。由于我还在学徒期,并且仍然认为自己是企业编程的初学者,我并没有真正试图推进我的观点,那就是使用数据库的对象关系映射器可以大大简化开发。开发团队中的其他程序员比我更有经验,所以我想我会按他们说的做。:-)

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

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

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

另外,如果你不太了解 NHibernate 框架,使用 NHibernate 可能会遇到不可预见的问题。例如,可以信任 Table.hbm.xml,在其中设置字符串的长度以自动验证。但是,我也可以想象基于“简单”SqlConnection 查询的数据访问层中存在类似的 bug。

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

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

45181 次浏览

There's been an explosion of growth with ORMs in recent years and your more experienced coworkers may still be thinking in the "every database call should be through a stored procedure" mentality.

Why would an ORM make things harder to debug? You'll get the same result whether it comes from a stored proc or from the ORM.

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

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

简短的回答是肯定的,确实有很好的理由。事实上,有些情况下你不能使用 ORM。

Case in point, I work for a large enterprise financial institution and we have to follow a lot of security guidelines. To meet the rules and regulations that are put upon us, the only way to pass audits is to keep data access within stored procedures. Now some may say that's just plain stupid, but honestly it isn't. Using an ORM tool means the tool/developer can insert, select, update or delete whatever he or she wants. Stored procedures provide a lot more security, especially in environments when dealing with client data. I think this is the biggest reason to consider. Security.

我在一个项目中没有使用 ORM 是非常成功的。这是一个项目

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

让 NHibernate 在水平分区结构中工作所需要的时间远远超过开发一个能够识别我们的分区方案的超级简单数据采集器所需要的时间。

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

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

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

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

There is no argument for #1 as copying and pasting queries and hardcoding in text gives no flexibility, and for #2 most orm's will wrap the original exception, will allow tracing the queries generated, etc, so debugging isnt rocket science either.

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

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

编辑: 我想再说一点。如果你的公司采用了 ORM 策略,这将进一步增强其价值,因为你将为使用和实现制定指导方针和实践,每个人都将进一步增强他们对所选框架的了解,从而减轻你提出的问题之一。此外,你将学习什么工作和什么不当情况出现时,最终将节省大量的时间和精力。

对于很多常见的问题,像 Hibernate 这样的 ORM 工具是上帝派来的,还有一些问题是它的障碍。我对你的项目了解不多,不知道是哪个。

Hibernate 的一个优点是,您只需要说三次: 每个属性都在类中提到,而。Xml 文件和数据库。对于 SQL 查询,您的属性位于类、数据库、选择语句、插入语句、更新语句、删除语句以及支持 SQL 查询的所有编组和解组代码中!事情很快就会变得一团糟。另一方面,你知道它是怎么运作的。你可以调试它。它就在你自己的持久层中,而不是埋藏在第三方工具的内部。

Hibernate 可能是斯波尔斯基漏洞抽象定律的典型代表。有一点偏离常规,您需要了解工具的深层内部工作原理。当您知道可以在几分钟内修复 SQL,但却花费数小时试图哄骗该死的工具生成合理的 SQL 时,这可能非常令人恼火。调试有时候是一场噩梦,但是很难说服那些没有做过调试的人。

编辑: 如果 iBatis.NET 不打算使用 NHibernate,并且希望控制其 SQL 查询,那么您可能需要查看 iBatis.NET。

编辑2: 这里有一个大红旗: “到目前为止,在 Stack Overflow 上被视为非常正常的良好实践,如单元测试或持续集成,在这里是不存在的。”那么,这些“有经验的”开发人员,他们在开发方面有什么经验呢?他们的工作保障?听起来你可能是那些对这个领域不感兴趣的人之一,所以不要让他们扼杀了你的兴趣。你需要保持平衡。奋起反抗。

首先,如果正确地集成,ORM 可以使您的开发生活变得更加容易,但是有一些问题,ORM 实际上可能会阻止您实现既定的需求和目标。

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

您应该知道,可以混合使用 ORM 和非 ORM 技术。我刚刚发现,有一些边缘情况下,ORM 不能支持您的需求,您必须绕过它们来处理这些情况。

There are two aspects of ORMs that are worrisome. First, they are code written by someone else, sometimes closed source, sometimes open source but huge in scope. Second, they copy the data.

第一个问题导致两个问题。你在依赖外人的代码。我们都会这样做,但不应轻易做出这样的选择。如果它不能满足你的需要呢?你什么时候才能发现?你生活在 ORM 为你画的盒子里。

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

Personally, i have (until recently) opposed to use an ORM, and used to get by with writing a data access layer encapsulating all the SQL commands. The main objection to ORMs was that I didn't trust the ORM implementation to write exactly the right SQL. And, judging by the ORMs i used to see (mostly PHP libraries), i think i was totally right.

现在,我的大部分 web 开发都是使用 Django,我发现包含的 ORM 真的很方便,而且由于数据模型首先用它们的术语表示,然后才用 SQL 表示,所以它确实完美地满足了我的需求。我确信它不会太难长大,需要手写 SQL 来补充; 但是对于 CRUD 访问已经足够了。

我不知道 NHibernate 怎么样,但我想它对于你所需要的大部分东西来说也是“足够好”的。但是如果其他程序员不信任它,它将成为每个数据相关错误的首要嫌疑人,使得验证变得更加乏味。

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

我认为也许当你在更大的系统上工作时,你可以使用像 CodeSmith 这样的代码生成工具,而不是 ORM... 我最近发现了这个: Cooperator Framework,它生成 SQL 服务器存储过程,也生成你的业务实体,映射器,网关,延迟负载和所有这些东西在 C # ... 检查一下... 它是由一个团队在阿根廷这里写的..。

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

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

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

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

The solutions to these are:

  1. 使代码可测试(使用 很可靠原则)
  2. 为尽可能多的代码编写自动化测试
  3. 尽可能经常地运行自动化测试

回到你的问题,你列出的两个反对理由看起来更像是无知。

不能手工编写 SELECT 查询(我猜这就是需要复制粘贴的原因)似乎表明迫切需要进行一些 SQL 培训。

我不使用 ORM 有两个原因:

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

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

  1. 速度

    使用 ORM 没有理由会比手工编码的数据访问慢。事实上,由于内置的缓存和优化,它可以更快。 A good ORM will produce a repeatable set of queries for which you can optimise your schema. 一个好的 ORM 还允许使用各种获取策略有效地检索相关数据。

  2. 复杂性

    关于复杂性,使用 ORM 意味着更少的代码,这通常意味着更少的复杂性。 许多使用手写(或代码生成)数据访问的人发现自己在“低级”数据访问库(比如为 ADO.Net 编写辅助方法)上编写自己的框架。这等同于更加复杂,更糟糕的是,它们很少被很好地记录下来,或者被很好地测试。
    如果你特别关注 NHibernate,那么像 Fluent NHibernate 和 Linq To NHibernate 这样的工具也可以软化学习曲线。

关于 ORM 的争论让我想到的是,那些声称使用 ORM 太难/太慢/无论如何都非常喜欢使用 Linq To Sql 或者 Type Datasets 的人。虽然 Linq To Sql 是朝着正确方向迈出的一大步,但是它仍然落后于一些开源 ORM。然而,类型化数据集和 Linq To Sql 的框架仍然非常复杂,使用它们来实现(Table = Class) + (基本 CRUD)是非常困难的。

My advice is that if, at the end of the day, you can't get an ORM, then make sure that your data access is separated from the rest of the code, and that you you follow the Gang Of Four's advice of coding to an interface. Also, get a Dependancy Injection framework to do the wiring up.

(这样的咆哮怎么样?)

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

我建议阅读 ORM 的缺点清单。

Http://blogs.tedneward.com/2006/06/26/the+vietnam+of+computer+science.aspx

For my self, I've found ORMs very useful for most applications I've written!

/Asger

The experience I've had with Hibernate is that its semantics are subtle, and when there's problems, it's a bit hard to understand what's going wrong under the hood. I've heard from a friend that often one starts with Criteria, then needs a bit more flexibility and needs HQL, and later notices that after all, raw SQL is needed (for example, Hibernate doesn't have union AFAIK).

同样,对于 ORM,人们很容易过度使用现有的映射/模型,这导致存在一个具有许多未初始化属性的对象。因此在查询之后,事务内部的 Hibernate 会进行额外的数据获取,这会导致潜在的速度减慢。同样不幸的是,Hibernate 模型对象有时会泄漏到视图体系结构层,然后我们会看到 LazyInitializationException。

要使用 ORM,一个人应该真正理解它。不幸的是,一个人很容易得到的印象是,它很容易,而它不是。

ORM 的最佳位置

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

You may well have a handful of queries that are better done by hand. In this case, don't be afraid to write a few stored procedures to handle this. Even if you intend to port your app across multiple DBMS platforms the database dependent code will be in a minority. Bearing in mind that you will need to test your application on any platform on which you intend to support it, a little bit of extra porting effort for some stored procedures isn't going to make a lot of difference to your TCO. For a first approximation, 98% portable is just as good as 100% portable, and far better than convoluted or poorly performing solutions to work around the limits of an ORM.

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

ORM 可能不是最适合的地方

In other cases there may be approaches that suit the application better than an ORM. Fowler's 企业应用体系结构模式 has a section on data access patterns that does a fairly good job of cataloguing various approaches to this. Some examples I've seen of situations where an ORM may not be applicable are:

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

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

  • 跨系统数据完整性非常重要的金融应用程序或其他类型的系统,特别是在使用具有两阶段提交的复杂分布式事务时。您可能需要比 ORM 更好地对事务进行微观管理。

  • High-performance applications where you want to really tune your database access. In this case, it may be preferable to work at a lower level.

  • Situations where you're using an incumbent data access mechanism like ADO.Net that's 'good enough' and playing nicely with the platform is of greater benefit than the ORM brings.

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

When you need to update 50000000 records. Set a flag or whatever.

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

Update 1 : Try also retrieving one record with only a few of its fields. (When you have a very "wide" table). Or a scalar result. ORMs suck at this too.

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

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

我发现,对于中等复杂的应用程序,绕过这些假设通常要花费我更多的时间,而不是简单地编写一个更直接的解决方案,比如: 查询数据,手动实例化新实体。

特别是,一旦您使用多列键或其他中等复杂的关系,而这些关系刚好超出了 ORM 在您下载代码时提供给您的方便示例的范围,您就可能遇到麻烦。

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

否则,让 ORMs 见鬼去吧。我现在认为它们基本上就是一种时尚。

不是为了回答这个问题,我想重新组织一下我最近听到的一句话。“一个好的 ORM 就像一个雪人,每个人都在谈论它,但没有人看到它。”

每当我把手放在 ORM 上时,我通常会发现自己在与这个 ORM 的问题/局限性作斗争。最后,是的,它做了我想要的,它被写在那个糟糕的文档的某个地方,但我发现自己又浪费了一个小时,我永远不会得到。任何人使用冬眠,然后在后期流利地冬眠都能理解我经历了什么。一直觉得“这个代码不在我的控制之下”真的很糟糕。

我没有指责或者说他们是坏人,但是我开始思考我所放弃的仅仅是为了在一个表达式中自动化 CRUD。现在我认为我应该使用 ORM 的更少,也许创建或找到一个解决方案,使数据库操作在最低限度。但只有我。我相信在这个 ORM 领域有些事情是错误的,但是我没有足够的技能来表达它。

我认为有很多很好的理由不使用 ORM。首先,我是一个。NET 开发人员和我喜欢坚持什么的美妙。NET 框架已经提供给我。它可以做任何我可能需要它做的事。通过这样做,您可以使用一种更加标准的方法,因此,在同一个项目中工作的任何其他开发人员都有更好的机会能够获取并运行这个项目。微软已经提供的数据访问能力相当充足,没有理由放弃它们。

我已经是一个专业的开发人员10年,领导多个非常成功的百万美元以上的项目,我从来没有一次编写应用程序,需要能够切换到任何数据库。你为什么要让客户这么做?仔细计划,选择适合您需要的数据库,并坚持使用它。就个人而言,SQLServer 可以做任何我需要做的事情。很简单,效果很好。甚至还有一个免费版本,支持多达10GB 的数据。哦,它的工作原理棒极了。NET.

我最近不得不开始几个使用 ORM 作为数据层的项目。我觉得这很糟糕,还有一些额外的东西,我不得不学习如何无缘无故地使用。在极其罕见的情况下,客户确实需要更改数据库,我本可以很容易地用比与 ORM 提供商开玩笑更少的时间重新处理整个数据层。

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

Otherwise I think ORMs are for developers that don't understand less is more, and think the more cool 3rd party tools they use in their app, the better their app will be. I'll leave things like this to the die hard uber geeks while I crank out much more great software in the meantime that any developer can pick up and immediately be productive with.

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

除此之外:

  • 通过不使用 ORM,您正在解决一个已经存在的问题 由大型社区或公司重复解决 资源。
  • 通过使用 ORM,数据访问层的核心部分将受益 从社区或公司的调试工作。

为了在参数中加入一些观点,请考虑使用 ADO.NET 相对于编写代码来解析表格数据流本身的优势。

I have seen ignorance of how to use an ORM justify a developer's disdain for ORMs For example: eager loading (something I noticed you didn't mention). Imagine you want to retrieve a customer and all of their orders, and for those all of the order detail items. If you rely on lazy loading only, you will walk away from your ORM experience with the opinion: "ORMs are slow." If you learn how to use eager loading, you will do in 2 minutes with 5 lines of code, what your colleagues will take a half a day to implement: one query to the database and binding the results to a hierarchy of objects. Another example would be the pain of manually writing SQL queries to implement paging.

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

不要让你的高级团队成员的经验把你拖向计算机科学发展的相反方向。我已经从事专业发展23年了,其中一个不变的就是老派人士对新事物的蔑视。ORM 对 SQL 的意义就像 C 语言对汇编语言的意义一样,你可以打赌,对 C + + 和 C # 的等价物正在形成。一行新校代码等于20行老校代码。