有没有充分的理由不使用ORM?

时间:2008-10-11 14:43:04

标签: c# nhibernate orm enterprise

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

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

  1. 可以使用SQL查询构建自己的数据访问对象,并将这些查询复制出Microsoft SQL Server Management Studio。
  2. 调试ORM可能很难。
  3. 所以,当然我可以用很多SELECT等构建我的数据访问层,但是在这里我想念自动连接,延迟加载代理类的优势以及如果一个表更低的维护工作量获取新列或重命名列。 (更新了大量SELECTINSERTUPDATE查询,而不是更新映射配置,还可能重构业务类和DTO。)

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

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

    (我应该补充一点,我认为这就像第一个基于.NET / C#的“大型”应用程序需要团队合作。良好实践,在Stack Overflow上看起来很正常,例如单元测试或持续集成,到目前为止还不存在。)

20 个答案:

答案 0 :(得分:55)

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

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

答案 1 :(得分:47)

ORM的最佳点

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

您可能会有一些手动更好的查询。在这种情况下,不要害怕编写一些存储过程来处理这个问题。即使您打算在多个DBMS平台上移植您的应用程序,依赖于数据库的代码也只占少数。请记住,您需要在您打算支持它的任何平台上测试您的应用程序,对某些存储过程进行一些额外的移植工作不会对您的TCO产生很大影响。对于第一个近似值,98%的便携式设备与100%便携式设备一样好,远远优于复杂或性能不佳的解决方案,可以在ORM的极限范围内工作。

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

ORM可能不是最合适的

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

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

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

  • 跨系统数据完整性很重要的财务应用程序或其他类型的系统,特别是如果您使用具有两阶段提交的复杂分布式事务。您可能需要对ORM能够支持的交易进行微观管理。

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

  • 您正在使用ADO.Net这样的现有数据访问机制,这种机制“足够好”并且与平台良好协作,这比ORM带来的好处更多。

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

答案 2 :(得分:37)

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

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

  1. 测试代码
  2. 维护代码
  3. 这些解决方案是:

    1. 使您的代码可测试(使用SOLID原则)
    2. 为尽可能多的代码编写自动化测试
    3. 尽可能多地运行自动化测试
    4. 提出你的问题,你列出的两个反对意见似乎更像是无知而不是其他任何事情。

      无法手动编写SELECT查询(我认为,这就是为什么需要复制粘贴)似乎表明迫切需要一些SQL培训。

      我不使用ORM有两个原因:

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

        1. 速度

          没有理由使用ORM比手动编码数据访问慢。事实上,由于内置的​​缓存和优化,它可以更快。 一个好的ORM将生成一组可重复的查询,您可以为其优化模式。 一个好的ORM还可以使用各种提取策略有效地检索相关数据。

        2. 复杂性

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

        3. 让我了解整个ORM辩论的事情是,声称使用ORM的人会过于强硬/慢速/使用Linq To Sql或Typed Datasets非常满意的人。虽然Linq To Sql是朝着正确方向迈出的一大步,但它仍然落后于一些开源ORM的落后时间。但是,Typed Datasets和Linq To Sql的框架仍然非常复杂,使用它们太远(Table = Class)+(基本CRUD)是非常困难的。

          我的建议是,如果在一天结束时,您无法获得ORM,那么请确保您的数据访问与其他代码分开,并且您遵循Gang Of Four的建议编码到接口。另外,获取一个Dependancy Injection框架来进行连接。

          (咆哮怎么样?)

答案 3 :(得分:32)

有很多常见问题,像Hibernate这样的ORM工具是神派,还有一些是阻碍它的地方。我对你的项目知之甚少,不知道它是什么。

Hibernate的一个优点是你只能说3次:在类,.hbm.xml文件和数据库中提到了每个属性。使用SQL查询,您的属性位于类,数据库,select语句,insert语句,update语句,delete语句以及支持SQL查询的所有编组和解组代码中!这可能会很快变得混乱。另一方面,你知道它是如何工作的。你可以调试它。它就在你自己的持久层中,而不是埋没在第三方工具的内部。

Hibernate可能是Spolsky的Leaky Abstractions法则的典型代表。稍微偏离常规路径,您需要了解该工具的深层内部工作原理。当你知道你可以在几分钟内修复SQL时,它可能会非常烦人,但你花了好几个小时试图哄骗你的dang工具来生成合理的SQL。调试有时候是一场噩梦,但很难说服那些没有去过那里的人。

编辑:你可能想看看iBatis.NET,如果他们不打算转向NHibernate,他们想要控制他们的SQL查询。

编辑2:这里有一个大红旗:“好的做法,在Stack Overflow上看起来很正常,例如单元测试或持续集成,到目前为止还不存在。”那么,这些“经验丰富”的开发人员,他们在开发方面经历了什么?他们的工作安全?听起来你可能是那些对这个领域不特别感兴趣的人,所以不要让他们扼杀你的兴趣。你需要保持平衡。打架。

答案 4 :(得分:29)

近年来,ORM的增长一直在增长,而您经验丰富的同事可能仍在考虑“每个数据库调用应通过存储过程”的心态。

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

我想我能用ORM想到的唯一真正的不利因素是安全模型的灵活性稍差。

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

答案 5 :(得分:12)

我参与了一个没有成功使用ORM的项目。这是一个项目

  1. 从一开始就必须横向扩展
  2. 必须快速发展
  3. 有一个相对简单的域模型
  4. 让NHibernate在水平分区结构中工作所需的时间比开发一个知道我们的分区方案的超级简单数据映射器花费的时间要长得多......

    因此,我在ORM工作的90%的项目都是非常宝贵的帮助。但是在某些非常具体的情况下,我可以看到不使用ORM是最好的。

答案 6 :(得分:11)

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

除了功能:

  • 通过不使用ORM,您正在解决已经存在的问题 大型社区或具有重要意义的公司反复解决 资源。
  • 通过使用ORM,您的数据访问层的核心部分受益 来自该社区或公司的调试工作。

要在参数中加入一些观点,请考虑使用ADO.NET与编写代码以自行解析表格数据流的优势。

我已经看到无知如何使用ORM证明开发人员对ORM的蔑视例如:渴望加载(我注意到你没有提到的东西)。想象一下,您想要检索客户及其所有订单,以及所有订单明细项目。如果你只依赖于延迟加载,那么你将从ORM经验中摒弃以下观点:“ORM很慢。”如果您学习如何使用预先加载,您将在2分钟内完成5行代码,您的同事将花费半天时间来实现:对数据库进行一次查询并将结果绑定到对象层次结构。另一个例子是手动编写SQL查询以实现分页的痛苦。

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

不要让你的高级团队成员的经验把你拉向与计算机科学发展相反的方向。我一直在专业发展23年,其中一个常数是老派对新人的蔑视。 ORMs是SQL语言,因为C语言是汇编语言,你可以打赌,C ++和C#的等价物正在逐步推进。一行新学校代码相当于20行老派。

答案 7 :(得分:11)

首先我要说的是,如果正确整合,ORM可以让您的开发生活更轻松,但是ORM实际上可以阻止您实现您声明的要求和目标存在一些问题。

我发现在设计具有高性能要求的系统时,我经常会遇到挑战,想方设法让系统更高效。很多时候,我最终得到了一个具有大量写入性能的解决方案(这意味着我们写的数据比我们读取数据的要多得多)。在这些情况下,我想利用数据库平台为我提供的设施来实现我们的性能目标(它是OLTP,而不是OLAP)。所以如果我使用的是SQL Server而且我知道我要写很多数据,为什么我不会使用批量插入......好吧,正如你可能已经发现的那样,大多数ORMS(我不知道是否即使只有一个人也没有能力利用平台特定的优势,如批量插入。

您应该知道可以混合使用ORM和非ORM技术。我刚刚发现有一些边缘情况,ORM无法满足您的要求,您必须为这些情况解决这些问题。

答案 8 :(得分:9)

何时需要更新50000000条记录。设置旗帜或其他。

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

更新1:尝试仅使用少数字段检索一条记录。 (当你有一个非常“宽”的表)。或者是标量结果。 ORM也很尴尬。

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

答案 9 :(得分:8)

我认为也许当你在更大的系统上工作时,你可以使用代码生成器工具,如CodeSmith而不是ORM ......我最近发现:Cooperator Framework生成SQL Server存储过程并生成业务实体,地图制作者,网关,懒惰和C#中的所有东西......看看它......它是由阿根廷的一个团队写的......

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

答案 10 :(得分:6)

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

现在,我的大部分Web开发都使用Django,我发现包含的ORM非常方便,并且由于数据模型首先在它们的术语中表达,并且仅在SQL的后期表达,因此它确实能够满足我的需求。我确信它不会太难以超出它并且需要补充手写的SQL;但对于CRUD访问来说绰绰有余。

我不知道NHibernate;但我想这对你需要的大部分内容来说也“足够好”。但如果其他程序员不相信它;它将成为每个数据相关错误的主要嫌疑人,使验证更加繁琐。

您可以尝试在您的工作场所逐步介绍它,首先关注小型“明显”的应用程序,例如简单的数据访问。过了一会儿,它可能会用在原型上,它可能不会被替换......

答案 11 :(得分:5)

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

答案 12 :(得分:4)

我认为不使用ORM有很多充分的理由。首先,我是一名.NET开发人员,我喜欢坚持.NET框架已经提供给我的内容。它做了我可能需要的一切。通过这样做,您可以采用更标准的方法,因此任何其他开发人员都可以在同一个项目中工作,从而能够获取所有项目并运行它。微软已经提供的数据访问功能非常充足,没有理由放弃它们。

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

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

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

否则我认为ORM适用于不太了解的开发人员,并且认为他们在应用中使用的第三方工具越多,他们的应用程序就越好。我会把这样的事情留给顽固的超级极客,同时我开发出更多优秀的软件,同时任何开发人员都可以拿起并立即提高工作效率。

答案 13 :(得分:3)

我建议阅读这个阅读列表,列出ORM的缺点。

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

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

/导演Asger

答案 14 :(得分:3)

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

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

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

答案 15 :(得分:3)

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

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

答案 16 :(得分:3)

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

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

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

答案 17 :(得分:3)

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

每当我把手放在ORM上时,我通常会发现自己正在努力解决ORM的问题/限制。最后,是的,它做了我想要的,它写在那个糟糕的文档的某处,但我发现自己又失去了一个小时,我永远不会得到。任何使用nhibernate,然后在postgresql上流利的nhibernate的人都会明白我曾经历过的。不断感觉“这段代码不在我的控制之下”真的很糟糕。

我没有指责或说他们不好,但我开始考虑我只是为了在单个表达式中自动化CRUD而给予的东西。现在我认为我应该少用ORM,也许创建或找到一个能够最少启用数据库操作的解决方案。但这只是我。我相信在这个ORM领域有些事情是错的,但是我没有足够的技巧来表达它没有。

答案 18 :(得分:2)

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

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

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

编写自己的框架可能很费力,而且经常会遗漏错误。

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

答案 19 :(得分:1)

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

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

特别是,一旦您使用多列密钥或其他中等复杂的关系,您可能会遇到障碍,这些关系不在您下载代码时ORM为您提供的便捷示例范围之外。< / p>

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

否则,与ORM一起下地狱。我现在认为它们基本上是一种时尚。