有没有好的理由不使用ORM?

在我的学徒期间,我使用了NHibernate来处理一些我自己编写和devise的小项目。 现在,在开始一个更大的项目之前,讨论如何devise数据访问以及是否使用ORM层。 由于我仍然在学徒阶段,仍然认为自己是企业编程的初学者,所以我没有真正推动我的观点,那就是使用对象关系映射到数据库可以减轻开发的负担。 开发团队中的其他编程人员比我更有经验,所以我想我会按照他们的说法去做。 🙂

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

  1. 可以用SQL查询构build自己的数据访问对象,并将这些查询从Microsoft SQL Server Management Studio中复制出来。
  2. debuggingORM可能很困难。

所以,当然,我可以build立我的数据访问层与很多SELECT等,但在这里我错过了自动连接,延迟加载代理类和较低的维护工作的优势,如果一个表得到一个新的列或列被重新命名。 (更新大量的SELECTINSERTUPDATE查询与更新映射configuration并可能重构业务类和DTO。)

另外,如果你不熟悉这个框架,使用NHibernate你可能会遇到无法预料的问题。 例如,可以信任Table.hbm.xml,在其中设置string的长度以自动validation。 不过,我也可以想象在基于“简单”SqlConnection查询的数据访问层中的类似错误。

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

(我应该补充一点,我认为这就像是第一个需要团队合作的“大”的基于.NET / C#的应用程序。堆栈溢出(Stack Overflow)中很正常的良好实践,如unit testing或持续集成 – 到现在为止。)

近年来,随着ORM的迅速发展,你的经验丰富的同事可能仍然会想“每一次数据库调用都应该通过存储过程”的思路。

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

我想用ORM唯一可以想到的损害是安全模型不够灵活。

编辑:我只是重新读你的问题,它看起来他们复制和粘贴到内联的SQL查询。 这使得安全模型与ORM相同,所以与ORM相比,这种方法绝对没有优势。 如果他们正在使用非参数化的查询,那么它实际上是一个安全风险。

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

举个例子,我为一家大型企业金融机构工作,我们必须遵循很多安全指导原则。 为了符合我们所遵循的规则和规定,通过审计的唯一方法是将数据存储在存储过程中。 现在有人可能会说这简直是愚蠢的,但实际上并非如此。 使用ORM工具意味着工具/开发人员可以插入,select,更新或删除他或她想要的任何内容。 存储过程提供了更多的安全性,特别是在处理客户数据的环境中。 我认为这是考虑的最大原因。 安全。

ORM的甜蜜点

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

你可能会有一些更好的手工查询。 在这种情况下,不要害怕编写一些存储过程来处理这个问题。 即使您打算跨多个DBMS平台移植您的应用程序,依赖于数据库的代码也将是less数。 请记住,您将需要在任何您希望支持的平台上testing您的应用程序,但对于某些存储过程,额外的移植工作不会对您的TCO产生很大的影响。 对于第一个近似值来说,98%的便携性和100%的便携性一样好,而且要比绕过ORM限制的复杂或者性能不佳的解决scheme好得多。

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

ORM可能不是最合适的

在其他情况下,可能有比ORM更适合应用程序的方法。 福勒的企业应用架构模式有一个关于数据访问模式的章节,对这种模式的编目做了相当好的工作。 我见过的一些ORM不适用的例子是:

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

  • 一个变体就是你inheritance一个不一定非常适合OR映射的数据模型。 如果(例如)你正在编写一个从外部接口填充或提取数据的接口,你可能会更好地使用数据库。

  • 金融应用程序或其他types的跨系统数据完整性非常重要的系统,尤其是在使用两阶段提交的复杂分布式事务时。 您可能需要比ORM能够支持的更好地pipe理您的交易。

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

  • 在使用像ADO.Net这样的现有数据访问机制的情况下,这个“足够好”,并且与平台搭配起来比ORM带来的好处更多。

  • 有时数据只是数据 – 例如,您的应用程序可能使用“事务”而不是“对象”,这是对域的合理看法。 一个例子可能是一个财务软件包,你有可configuration的分析领域的交易。 虽然应用程序本身可能build立在面向对象的平台上,但它并不局限于单一的业务领域模型,并且可能不仅仅是GL代码,帐户,文档types和六个分析领域。 在这种情况下,应用程序不知道这样的业务领域模型,而且对象模型(超出分类帐结构本身)与应用程序无关。

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

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

  1. testing你的代码
  2. 维护你的代码

这些解决scheme是:

  1. 让你的代码可testing(使用SOLID原则)
  2. 为尽可能多的代码编写自动化testing
  3. 尽可能经常运行自动化testing

回答你的问题,你列出的两个反对意见似乎更像是无知。

不能手动编写SELECT查询(我猜这就是为什么需要复制粘贴)似乎表明需要一些SQL培训。

有两个原因我不使用ORM:

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

关于ORM(特别是NHibernate)的通常的回击是:

  1. 速度

    没有理由使用ORM比手动编码的数据访问慢。 事实上,由于内置caching和优化,它可以更快。 一个好的ORM将产生一个可重复的查询集合,您可以优化您的模式。 一个好的ORM也将允许使用各种获取策略有效地检索相关数据。

  2. 复杂

    关于复杂性,使用ORM意味着更less的代码,这通常意味着更less的复杂性。 许多使用手写(或代码生成)数据访问的人发现自己在“低级”数据访问库(如编写ADO.Net的辅助方法)上编写自己的框架。 这些等同于更复杂的情况,更糟糕的是,它们很less有文档logging,或者经过很好的testing。
    如果你正在专门研究NHibernate,那么像Fluent NHibernate和Linq To NHibernate这样的工具也会使学习曲线变软。

让我关于整个ORM辩论的事情是,那些声称使用ORM的同样的人将会太难/慢/无论是那些使用Linq To Sql或Typed Datasets的人都非常高兴。 虽然Linq To Sql是朝着正确方向迈出的一大步,但是在开放源代码ORMs的一些地方仍然是光年。 然而,Typed Datasets和Linq To Sql的框架仍然非常复杂,使用它们过分(Table = Class)+(基本的CRUD)是非常困难的。

我的build议是,如果在一天结束的时候,你不能得到一个ORM,那么确保你的数据访问与其他代码是分开的,并且你遵循“四人帮”的编码build议一个界面。 另外,得到一个Dependancy Injection框架来完成接线。

(这怎么是一个咆哮?)

像Hibernate这样的ORM工具有很多的常见问题,都是上帝寄来的,有些是阻碍的地方。 我不太了解你的项目,知道它是什么。

Hibernate的强项之一是你只能说3遍:每个属性在类,.hbm.xml文件和数据库中都有提到。 使用SQL查询,您的属性位于类,数据库,select语句,插入语句,更新语句,删除语句以及支持您的SQL查询的所有编组和解组代码中! 这可能会变得凌乱。 另一方面,你知道它是如何工作的。 你可以debugging它。 在你自己的持久层中,没关系,没有埋在第三方工具的内部。

hibernate可能是斯波尔斯基泄漏定律的一个海报。 稍微走一步,你需要知道这个工具的深​​层内部工作原理。 当你知道你可以在几分钟内修复SQL的时候,这可能是非常烦人的,但是你却花费了好几个小时来试图哄骗你的dang工具生成合理的SQL。 debugging有时是一个噩梦,但很难说服那些不在那里的人。

编辑:你可能想看看iBatis.NET,如果他们不会被扭转关于NHibernate和他们想要控制他们的SQL查询。

编辑2:这是一个大红旗,虽然:“良好的做法,在堆栈溢出,如unit testing或持续集成,这是非常正常的现在这里是不存在的。 那么,这些“有经验”的开发者,他们在开发中经历了什么? 他们的工作安全? 这听起来像你可能是在这个领域不是特别感兴趣的人,所以不要让他们杀了你的兴趣。 你需要成为平衡。 打架。

我在一个不使用ORM的项目上工作很成功。 这是一个项目

  1. 必须从一开始就水平scalealbe
  2. 必须迅速发展
  3. 有一个相对简单的领域模型

NHibernate在水平分区结构中工作的时间要比开发一个能够意识到我们分区scheme的超级简单数据映射器所花费的时间长得多。

所以,我在ORM工作的项目中有90%是非常宝贵的帮助。 但是有一些非常特殊的情况,我可以看到不使用ORM是最好的。

首先让我们说一下,如果整合得当,ORM可以使你的开发生活变得更容易,但是ORM实际上可以阻止你实现你所要求的要求和目标的问题有一些。

我发现在devise具有较高性能要求的系统时,我常常想要find使系统更高性能的方法。 很多时候,我会得到一个写入性能很好的解决scheme(这意味着我们写数据比读数据要多得多)。 在这些情况下,我想利用数据库平台提供给我的设施,以实现我们的性能目标(即OLTP,而不是OLAP)。 所以,如果我使用SQL Server,并且我知道我有很多数据要写,为什么我不使用批量插入…好吧,正如你可能已经发现的,大多数ORMS(我不知道是否即使是单一的)也没有能力利用平台特定的优势,如批量插入。

你应该知道你可以融合ORM和非ORM技术。 我刚刚发现有一些ORM不能支持你的需求的边缘情况,你必须在这些情况下解决它们。

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

除了特点:

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

为了说明一些观点,可以考虑使用ADO.NET与写代码来parsing表格数据stream的优点。

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

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

不要让高级团队成员的经验把你拖到与计算机科学发展相反的方向。 我一直在专业发展23年,其中一个常数是老派对新人的蔑视。 对于C语言来说,ORM就是SQL,所以你可以打赌,C ++和C#的等价物已经到来了。 一行新校代码等于20行老校。

当你需要更新50000000条logging时。 设置一个国旗或其他。

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

更新1:也尝试检索一个logging只有其几个领域。 (当你有一个非常“宽”的表)。 或者是一个标量结果。 ORM也吸取这一点。

更新2 :看来,EF 5.0testing版承诺批量更新,但这是非常热的消息(2012年1月)

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

我认为这是编码整个数据访问层和使用ORM之间的中间…

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

现在,我的web开发大部分都是使用Django,而且我发现包含的ORM真的很方便,而且由于数据模型首先expression了它们的含义,而后来在SQL中,它完全适合我的需求。 我相信它不会太难以超越它,需要用手写的SQL来补充; 但对于CRUD访问是绰绰有余的。

我不知道NHibernate; 但是我想这对于你所需要的大部分也是“足够好”的。 但是如果其他编码者不相信它, 它将成为每个数据相关错误的主要嫌疑犯,使validation更加乏味。

你可以尝试在你的工作场所逐渐引入它,首先把注意力放在小的“明显的”应用上,比如简单的数据访问。 一段时间后,它可能会用于原型,它可能不会被取代…

如果它是OLAP数据库(例如,用于报告/分析的静态只读数据等),那么实施ORM框架是不合适的。 相反,使用数据库的本地数据访问function(如存储过程)将是更可取的。 ORM更适合于事务型(OLTP)系统。

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

我之前没有使用过Hibernate,但是有一点我注意到,有一些“现成”的ORM解决scheme缺乏灵活性。 我相信这取决于你和谁一起去做什么。

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

第一个问题导致两个问题。 你是依靠外人的代码。 我们都这样做,但不能掉以轻心。 如果它不做你所需要的呢? 你什么时候发现这个? 你住在你的ORM为你绘制的盒子里面。

第二个问题是两阶段提交之一。 关系数据库正被复制到对象模型。 你改变对象模型,它应该更新数据库。 这是一个两阶段提交,而不是debugging的最简单的事情。

我build议这个阅读的ORM的缺点列表。

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

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

/导演Asger

我对Hibernate的经验是,它的语义是微妙的,当出现问题时,很难理解底下发生了什么问题。 我从一个朋友那里听说,经常有一个人从Criteria开始,然后需要更多的灵活性,需要HQL,后来发现需要原始的SQL(例如,Hibernate没有union AFAIK)。

另外,对于ORM,人们很容易过度使用现有的映射/模型,这导致有一个对象具有许多没有启动的属性。 因此,在查询之后,Hibernate内部的事务使得额外的数据获取,这导致潜在的减速。 另外可悲的是,hibernate模型对象有时会泄露到视图体系结构层,然后我们看到LazyInitializationExceptions。

要使用ORM,应该真的了解它。 不幸的是,人们很容易感觉到它很容易,而不是。

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

每当我把手放在一个ORM上时,我通常会发现自己正在为这个ORM的问题/局限性而苦苦挣扎。 最后,是的,它是做我想做的,它写在那个糟糕的文件的某处,但我发现自己失去了一个小时,我永远不会得到。 任何人使用nhibernate,然后stream利的postgresql nhibernate会明白我已经通过。 “这个代码不在我控制之下”的不断的感觉真的很糟糕。

我没有指责或说他们不好,但我开始考虑我放弃了什么,只是在一个expression式中自动化CRUD。 现在,我认为我应该less用ORM,可能会创build或find一个解决scheme,使数据库操作至less。 但是这只是我。 我相信在这个ORM领域有些东西是错误的,但是我没有足够的技巧去expression它。

我认为有很多很好的理由不使用ORM。 首先,我是一名.NET开发人员,我喜欢坚持.NET Framework已经提供给我的东西。 它做我可能需要的一切。 通过这样做,您可以采用更加标准的方法,因此任何其他开发人员在同一个项目中工作的可能性都会大大提高。 微软已经提供的数据访问function非常充足,没有理由放弃它们。

我已经做了10年的专业开发人员,领导了多个非常成功的百万美元项目,而且我从来没有写过一个需要能够切换到任何数据库的应用程序。 为什么你会想要一个客户做到这一点? 仔细规划,select合适的数据库,并坚持下去。 个人而言,SQL Server已经能够做我曾经需要做的任何事情。 这很容易,而且效果很好。 甚至有一个免费版本可以支持10GB的数据。 哦,它和.NET很好。

我最近不得不开始使用ORM作为数据层的几个项目。 我觉得这很糟糕,还有一些额外的东西我不得不学习如何使用。 在非常罕见的情况下,客户确实需要更改数据库,我可以在比ORM供应商花费更less的时间内轻松地重新整理数据层。

Honestly I think there is one real use for an ORM: If you're building an application like SAP that really does need the ability to run on multiple databases. Otherwise as a solution provider, I tell my clients this application is designed to run on this database and that is how it is. Once again, after 10 years and a countless number of applications, this has never been a problem.

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.

I think that using an ORM is still a good idea. Especially considering the situation you give. It sounds by your post you are the more experienced when it comes to the db access strategies, and I would bring up using an 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.

As for validation, using an ORM will also usually allow much easier time developing validation strategies, on top of any built in validation.

Writing your own framework can be laborious, and often things get missed.

EDIT: I wanted to make one more point. If your company adopts an ORM strategy, that further enhances its value, as you will develop guidelines and practices for using and implementing and everyone will further enhance their knowledge of the framework chosen, mitigating one of the issues you brought up. Also, you will learn what works and what doesnt when situations arise, and in the end it will save lots of time and effort.

Every ORM, even a "good one", comes saddled with a certain number of assumptions that are related to the underlying mechanics that the software uses to pass data back and forth between your application layer and your data store.

I have found that for moderately sophisticated application, that working around those assumptions usually takes me more time than simply writing a more straightfoward solution such as: query the data, and manually instantiate new entities.

In particular, you are likely to run into hitches as soon as you employ multi-column keys or other moderately-complex relationships that fall just outside the scope of the handy examples that your ORM provided you when you downloaded the code.

I concede that for certain types of applications, particularly those that have a very large number of database tables, or dynamically-generated database tables, that the auto-magic process of an ORM can be useful.

Otherwise, to hell with ORMs. I now consider them to basically be a fad.