代码之家  ›  专栏  ›  技术社区  ›  Frustrating Developments

ORM与手工编码数据访问层

  •  19
  • Frustrating Developments  · 技术社区  · 16 年前

    我有点害怕问这个问题,因为它可能会引发一场战争,所以我想真正清楚我在寻找什么。我在找一个原因,为什么你会或曾经跳过一种或另一种方式,也为项目添加到我的列表。我在找大票,大爆炸物品。另外,产品特定的项目,如果它们真的相关的话,可能是。在这一点上,我试图评估ORM和手册,而不是产品A和产品B。

    ORM优势

     - Quick to code and low maintenance (in some/most scenarios) 
     - Additional features for "free" (no developer effort)
    

    手工编码的优点

     - More Efficient (at runtime, maybe not at dev time?)
     - Less layers of complexity
     - Most ORMS seem to struggle with being retricted to sprocs only
    

    为了完全公开,我真的不喜欢“某物”执行代码 我的 如果我认为合适的话,我不能直接修改数据库,但是我可以看到一个ORM潜在的大量开发时间副标题。

    我在一个.NET的世界里可能也值得一提

    [编辑] (问题在 Using an ORM or plain SQL? 似乎回答了许多问题,并强调了绩效的重要性)

    所以,稍微改变一下我的问题

    是否有人在早期阶段使用ORM构建了一个应用程序,然后逐渐被手工编码的DAL所取代?这种方法的缺陷是什么?

    [进一步编辑-现在就进入问题的核心] 有一个网站能够对我的数据库执行任何SQL是可怕的。如果所有的访问都是通过存储过程进行的,我的数据库将处于良好、安全、舒适的隔离状态。使用专门的存储过程可以删除大量(如果不是全部)SQL注入攻击向量。对此有何评论?

    16 回复  |  直到 13 年前
        1
  •  15
  •   Nick    16 年前

    我们最初使用JPA编写了一个应用程序,从它投入生产的那天起,我们就后悔了。ORM正在进行的数据库调用的数量是天文数字,因此我们现在已经开始了利用Spring的JDBC助手类,使用好的ol风格的JDBC重写应用程序的过程。从ORM开始的陷阱是,我们花了大量时间学习JPA,最后我们必须用JDBC替换它,这样我们的应用程序就可以更具可扩展性,而无需向Oracle RAC添加其他3个节点。因此,如果平衡一下,JDBC的控制和精度就值得您编写额外的代码行。而且,大多数人不理解SQL不是可以生成和期望执行的东西。为了获得最大的性能,必须对它进行编写和调整。

        2
  •  7
  •   geofftnz    16 年前

    我用亚音速做了几个大项目。我并不主张使用一个ORM而不是另一个,但是如果没有这个ORM,我就不能做另一个与数据库相关的项目。当我更改数据库结构时,可以重新生成整个数据库访问层,也可以在一个位置添加影响整个数据库层的功能。

    问题是,您必须了解它如何与数据库交互,否则在执行代码时会有写(严重)代码的风险。您的ORM工具可能会为您提供一个面向对象的数据视图,但是您可能会发现为了进行简单的处理,您正在将整个表流式传输到客户机。数据库擅长关联和过滤数据,因此请确保它仍然具有该作业。具有讽刺意味的是,Subsonic缺少连接(在我使用的版本中)有助于实现这一点,因为它迫使我创建DB视图,以便在需要时组合数据。

    我的一个朋友和一个开发内部ORM工具的人一起工作。它有一个很好的特性,即通过遍历外键本地缓存数据库中可能需要的所有内容。缺点是从数据库的一行中读取一列会导致超过11000个select语句。

        3
  •  6
  •   Otávio Décio    16 年前

    我已经写和维护自己的ORM 8年了。它从Java开始,然后转换成C语言。我无法想象没有它就写任何数据库支持的系统。它比nhibernate简单得多,没有所有的特性,但是它完成了任务,而且速度非常快,即使它广泛地使用反射,因为它用对DAO类定义的反射替换了XML配置。

    我对此很满意,不会使用任何其他方法。

    编辑:关于SQL注入攻击:我使用这个ORM开发的一个最近的系统被广泛审计,绝对不允许注入。原因很简单:它动态生成SQL,并且 总是 使用参数,不使用字符串串联。

        4
  •  5
  •   Chris Holmes    16 年前

    几周前,我开始开发一个新项目。我完全控制了我可以使用的工具。我从DB40开始,因为我想完全消除这个问题;我只想直接持久化我的对象,忘记ADO.NET或/M。但是DB40有问题,所以我不得不放弃它。

    我的下一个选择是ado.net,因为我认为它将是快速和简单的。但我不得不写太多的代码,使用太多的“字符串SQL”,而这只是一项家务。我是说,那是一个皇家皮塔,用它编码了两个仓库后,我想割腕。

    我的第三个选择是氨气。我以前在需要使用断开连接的对象的情况下遇到过NHibernate问题(这次也是这样,所以我花了三次尝试才能找到它)。但那是1.2的氨气。这次我得到了2.0二进制文件,更新断开连接的对象时没有任何问题。我还必须写更少的代码行,当我需要重构东西时,这是非常简单的,这可能是因为我的设计发生了快速的变化。

    我现在用NHibernate卖。它似乎也高度优化。老实说,我找不到任何负面影响。而且没有存储过程。

    我知道这是我的或/我的选择,我再也不会直接写ADO.NET了。

        5
  •  3
  •   BuddyJoe    16 年前

    我为此奋斗了几年。看了很多东西。在过去的三个月里,我意识到“为什么我要把这些时间浪费在这上面”。我认为ORM是一个已解决的问题。我宁愿相信一些完全专注于ORM的团队来编写ORM层,而不是我。在精神上,我准备好迎接新的挑战。

    我的选择是氨气。我现在真是个新手。但我也喜欢使用流畅的NHibernate或Castle ActiveRecord。这似乎就是思想共享的地方。

    但不确定我会在“一切都是一个存储过程”的世界里做什么。

        6
  •  3
  •   buurtnerd    15 年前

    你吃过红豆吗?在开发阶段,它是流体,易于使用,而在生产模式(冻结)它的快速。 http://redbeanphp.com

        7
  •  3
  •   charles    13 年前

    我认为,ORM在一开始只是“快速编码”,特别是如果您没有现有的已安装模式。 一旦您需要开始从系统中榨取更多的性能,您将需要一个ORM可以“快速处理”。

    我发现它们是一罐虫子。

        8
  •  1
  •   Craig    16 年前

    存储过程不会消除SQL注入的风险。可能在代码中进行concat查询的人在存储过程中也可能这样做。任何好的ORM都不会做字符串连接,所以没有问题。

        9
  •  1
  •   seanb    16 年前

    我继承了一个用nhib和mygeneration创建的web应用程序,不幸的是没有得到svn repo,也没有初始模板(arrgg)。

    保留了用于创建/更新/删除后端内容的nhibernate,但是前端(只读)实现得有点不明智,运行起来像一条两腿狗,现在正在用普通的ado.net重写,速度快了10倍。

    我不是说这是因为NHibernate,这是因为开发人员不知道他们发送了多少垃圾线,并假设盲目使用一个工具将意味着他们不必考虑它。

    出于只读查询的目的,您通常可以让它们更高效地手工编写。

    对于必须向数据库写入的内容,通常更容易(而不是慢得多)让一个合适的ORM来完成。

    我个人喜欢亚音速,我发现它在中型项目中表现很好,如果你发现了一个瓶颈,你可以用手来解决它。

    工具是很好的,任何能给我更多周末的东西都是双倍的好,但是在你的耳朵之间没有替代工具。

        10
  •  1
  •   dkretz    15 年前

    对存储过程问题的注释。无论功能是如何写入、DAL、ORM、存储过程的,都将涉及到SQL。如果您使用存储过程,那么您可以在内部编写SQL,并且在有用的抽象中构建SQL相对容易。如果使用DAL,则编写SQL,但在实践中,它更可能是不可替代的SQL,并且增加了对注入的暴露。如果您使用ORM,该工具将编写SQL(尽管您最终要对其负责,包括可注入性)。imho,运动部件最少(尤其是你知道和理解的部件)更好。

        11
  •  1
  •   Firo    13 年前

    我不得不重写一个使用对象数据库的生产应用程序的DAL。我们希望同时支持对象数据库和SQL数据库。一些我真的不想实现的特性,这些特性已经存在了

    • 使用querywise覆盖的透明Lazyloading
    • 实体标识(始终获取相同实体的相同引用)
    • 插入/更新批处理
    • 选择分批(NHibernate期货)
    • ID生成
    • 将查询API转换为SQL(由于查询API的模块化性质,标准是完美的)

    这就是为什么我选择NHibernate作为我的ORM,我很高兴。我免费得到了一些不错的功能。

    • 类的自动应用(总共3页代码来生成整个映射)
    • Linq支持(是否尝试过自己实现Linq提供程序?)
    • 免费大面积伐木
    • 使用InMemory sqlite更容易进行单元测试
    • 支持不同的数据库提供程序
    • 模式生成非常简单(不必为不同的DB提供程序维护任何生成脚本)
    • 并发控制
    • n/hibernate的文档是关系技术的一个很好的学习资源

    我无法想象如何用手工编写性能比nhibernate生成的更好的SQL。反对:

    • 当只需要很少的属性时加载整个对象-->始终有投影到DTOS或C 3.0中的匿名类型(setProjection()/select())
    • 许多选择而不是联接--在需要的地方使用预先加载(setFetchMode()/Fetch())
    • 经过调整的SQL总是比生成的SQL更具性能-->体系结构优化>>微观优化,使用ORM,由于代码较少且重复逻辑较少,因此更容易重构体系结构(尝试在手写DAL中将类似一对多对多的内容更改为多)
        12
  •  0
  •   Webjedi    16 年前

    你不需要放弃你的存储过程或手工制作的SQL与一个良好的ORM,如NHibernate。

    事实上,我已经替换了我的ORM数据访问方法,这一点都不难,它是两个世界中最好的。

        13
  •  0
  •   NetHawk    16 年前

    我已经将Castle项目与NHibernate的活动记录实施用于个人项目。该项目从未部署,部分原因是我无法使用我所做的ORM选择。

    我决定使用ORM的原因是因为我希望能够在不更改代码的情况下从SQL Server切换到MySQL。在实际的项目中,我已经决定使用SQL Server,并且当您知道数据库不会改变时,只使用传统的三层方式编写数据层更容易。 但是对于个人项目,我使用共享托管,而MySQL是一个更便宜的解决方案。

    我和卡斯尔一起去的原因是因为它很容易使用。使用Visual Studio的ActiveWriter插件,我可以使用设计器(类似于Linq to SQL设计器)生成类和数据库,它似乎与我的ORM应该如何指示应用程序体系结构的心理模型很匹配。

    我在那个ORM上遇到的问题是,我找不到有关如何正确优化它的信息。它正在对数据库进行非常大的调用。(为获取用户而生成的SQL查询在我登录时是1MB文本。)

    所以,我使用ORM,提前节省了很多工作,但是当我试图解决框架生成太多SQL的问题时,我遇到了困难。(我还在慢慢地工作)。

    即使我没有找到完美的解决方案,我仍然会尝试其他个人项目的ORM,因为只有我自己,我想把我的项目时间花在有趣的代码上,而不是数据层上。

    然而,在工作中,我可能不会太快建议我们使用ORM,在我成为专家之前(可能是在我得到几个工作项目之后)。

        14
  •  0
  •   Shiny    15 年前

    很好的问题和答案。 我也刚刚涉及到这些问题。 比起手工编码的DAL,我更喜欢亚音速ORM。

        15
  •  0
  •   staticsan    15 年前

    好吧,这是针对PHP应用程序的,而不是针对.NET应用程序的,但我认为相同的特性很重要。

    几年前我重新编写了一个基于数据库的PHP内部网应用程序。正如许多“刚刚成长”的PHP应用程序所特有的那样,它没有使用任何形式的ORM,并且有很多重复的代码,其中很多都以不同的方式组装类似的查询。

    我粗略地看了一下一些ORM框架,但它们都有一个大问题:它们需要定制来在我们的结构中工作。缺少的最大组件是数据库可伸缩性。所以我写了自己的处理程序。然后,继续构建我们自己的基于对象的数据层是一件简单的事情。我们必须实现我们想要的特性,这也是我们需要的。

    回想起来,这是一个非常有用的练习。这意味着我现在知道ORM层是如何工作的,以及它们是如何工作的。它还与大量数据库扩展的趋势背道而驰,因为它把问题提到了应用程序中,应用程序中有关于数据的知识。

        16
  •  0
  •   User1    15 年前

    我在.NET中使用数据集非常成功。我们有一个SOAP端点,它首先用.xsd验证输入。然后,您可以使用规则引擎进行一些验证。然后…

    如果请求插入数据:

    • 对数据集使用getxml()可转换为XML。
    • 将XML发送到使用 OPENXML 在SQLServer中。

    如果请求选择数据:

    • 编写一个存储过程,用多个select语句输出数据。
    • 将数据加载到数据集中(确保在需要时建立“嵌套”关系)。
    • 对数据集使用getxml()可转换为SOAP中使用的XML。

    我已经在几个生产环境中成功地使用了这个过程。如果您知道只使用SQL Server,那么这就简单快捷了。