哪个更好?或者使用和或映射器与 SP 的?如果您已经有一个带有 SP 的系统,那么 OR 映射器值得吗?
15 回答
我喜欢 ORM,因为您不必重新发明轮子。话虽如此,这完全取决于您的应用程序需求、开发风格和团队的风格。
这个问题已经讨论过了为什么 NHibernate 生成参数化 SQL 的速度和存储过程一样快?
存储过程没什么好说的。10 年前有必要,但使用存储过程的每一个好处都不再有效。两个最常见的论点是关于安全性和性能。“通过网络发送东西”的废话也不成立,我当然可以动态地创建一个查询来完成服务器上的所有事情。sproc 支持者不会告诉您的一件事是,如果您在合并发布上使用列冲突解决方案,它会使更新变得不可能。只有自认为是数据库霸主的 DBA 才会坚持使用存储过程,因为它使他们的工作看起来比实际更令人印象深刻。
这已在前面的问题中详细讨论过。
在我的工作中,我们主要做业务线应用程序——合同工作。
对于这种类型的业务,我是 ORM 的忠实粉丝。大约四年前(当时 ORM 工具还不太成熟),我们研究了 CSLA 并推出了我们自己的简化 ORM 工具,我们在大多数应用程序中都使用了该工具,包括一些拥有 100 多个表的企业级系统。
我们估计这种方法(当然包括大量代码生成)在我们的项目中可以节省高达 30% 的时间。说真的,这很荒谬。
有一个小的性能折衷,但只要您对软件开发有充分的了解,它就无关紧要。总是有例外需要灵活性。
例如,如果可能,仍应在专门的存储过程中处理极其数据密集的批处理操作。如果您可以在数据库上的存储过程中完成,您可能不想通过网络发送 100,000 条巨大的记录。
这是新手开发人员无论是否使用 ORM 都会遇到的问题类型。他们只需要看到结果,如果他们有能力,他们就会得到它。
我们在 Web 应用程序中看到的是,通常最难解决的性能瓶颈不再与数据库相关,即使使用 ORM 也是如此。相反,由于带宽、AJAX 开销等原因,它们位于前端(浏览器)。如今,即使是中端数据库服务器也非常强大。
当然,其他在更大的高需求系统上工作的商店可能会有不同的体验。:)
存储过程不言自明。或映射器是特定于语言的,并且经常添加图形减速。
存储过程意味着您不受语言界面的限制,您只需以向前兼容的方式添加到数据库的新界面。
我个人对 OR Mappers 的看法是,它们的存在凸显了流行的数据库结构中的一个设计缺陷。数据库开发人员应该意识到人们试图通过复杂的 OR-Mapper 完成的任务,并创建有助于执行此任务的服务器端实用程序。
OR Mappers 也是“泄漏抽象”综合症的史诗目标(Joel On Software: Leaky Abstractions)
由于抽象层不是通灵的,因此很容易找到它无法处理的东西。
在我看来,存储过程更好,因为它们可以具有独立于基础表的安全配置。
这意味着您可以允许特定操作,而不会允许对特定表进行写入/读取。它还限制了人们在发现 SQL 注入漏洞时可能造成的损害。
绝对是 ORM。更灵活、更便携(通常它们倾向于内置便携性)。如果速度很慢,您可能希望在热点中使用缓存或手动调整的 SQL。
通常,存储过程在可维护性方面存在几个问题。
- 与应用程序分开(现在必须在两个地方进行很多更改)
- 通常更难改变
- 更难置于版本控制之下
- 更难确保它们已更新(部署问题)
- 便携性(已经提到)
我个人发现 SP 在性能方面往往更快,至少对于我定期执行的大型数据项而言。但我知道很多人对 OR 工具发誓,不会做任何其他事情。
我认为使用 OR 映射器将提高应用程序源代码的可读性和可维护性,而使用 SP 将提高应用程序的性能。
它们实际上并不相互排斥,尽管就您而言,它们通常是相互排斥的。
使用对象关系映射的优点是您可以交换数据源。不仅是数据库结构,您还可以使用任何数据源。随着 Web 服务/面向服务的体系结构/ESB 的出现,在大型公司中,考虑拥有比存储过程中更高级别的关注点分离是明智的。但是,在较小的公司和永远不会使用不同数据源的应用程序中,SP 可以很好地满足要求。最后一点,没有必要使用 OR 映射器来获得抽象。我以前的团队通过简单地使用使用 Spring.NET 的适配器模型插入数据源而取得了巨大的成功。
@肯特弗雷德里克
我个人对 OR Mappers 的看法是,它们的存在凸显了流行的数据库结构中的一个设计缺陷”
我认为您在谈论关系模型和面向对象模型之间的区别。这实际上是我们需要 ORM 的原因,但这些模型的实现是故意完成的——它不是设计流程——它只是历史上的结果。
使用已确定性能瓶颈的存储过程。如果你还没有发现瓶颈,你在做什么过早的优化?
在您关心对特定表的安全访问时使用存储过程。
如果您有一个 SQL 向导,他准备坐下来编写复杂的查询,这些查询将遗留数据库中的大量表连接在一起,请使用存储过程,以完成 OR 映射器中难以完成的事情。
对数据库的其他(至少)80% 使用 OR 映射器:选择和更新是如此例行,以至于仅通过存储过程进行访问是手动编码中毫无意义的练习,并且更新如此罕见以至于没有性能成本。使用 OR 映射器来自动化简单的事情。
大多数 OR 映射器可以与存储的过程进行通信以完成其余的工作。
你不应该使用存储过程,假设它们比字符串中的 sql 语句更快,这在 MS SQL 服务器的最后几个版本中不一定是这种情况。
您不需要使用存储过程来阻止 SQL 注入攻击,还有其他方法可以确保您的查询参数是强类型的,而不仅仅是字符串连接。
您不需要使用 OR 映射器来获取 POCO 域模型,但它确实有帮助。
如果您已经有一个作为存储过程公开的数据 API,那么您需要证明对 ORM 进行重大架构改革是合理的。
对于绿地构建,我会评估几件事:
- 如果团队中有专门的 DBA,我会倾向于 sprocs
- 如果有多个应用程序接触同一个数据库,我会倾向于使用 sprocs
- 如果永远不可能进行数据库迁移,我会倾向于使用 sprocs
- 如果我想在数据库中实现 MVCC,我会倾向于 sprocs
- 如果我将其部署为可能具有多个后端数据库(MySql、MSSql、Oracle)的产品,我会倾向于 ORM
- 如果我的时间紧迫,我会倾向于 ORM,因为它是一种更快的方式来创建我的域模型并使其与数据模型保持同步(使用适当的工具)。
- 如果我以多种方式(Web 应用程序、Web 服务、RIA 客户端)公开相同的域模型,我将倾向于 ORM,因为然后数据模型隐藏在我的 ORM 外观后面,使健壮的域模型更有价值我。
我认为性能有点像红鲱鱼。hibernate 的性能似乎几乎与手动编码的 SQL 一样好或更好(由于它的缓存层),并且很容易在存储过程中编写错误的查询。
最重要的标准可能是团队的技能和长期的数据库可移植性需求。
那么SP已经在那里了。真的能做到这些是没有意义的。我想将映射器与 SP 一起使用是否有意义?
“我正试图钉钉子。我应该用鞋跟还是玻璃瓶?”
存储过程和 ORM 对开发人员(尽管不一定分别对 DBA 或架构师而言)来说使用起来既困难又烦人,因为它们会产生启动成本和更高的维护成本,而这并不能保证得到回报。
如果期望在系统的生命周期内需求不会发生太大变化,那么两者都会得到很好的回报,但是如果您构建系统以首先发现需求,它们就会妨碍您。
像 LINQ 和 ActiveRecord 这样的直接编码 SQL 或准 ORM 更适合构建到发现项目(企业中发生的项目比 PR 希望你想象的要多得多)。
存储过程在与语言无关的环境或需要对权限进行细粒度控制的环境中效果更好。如果您的 DBA 比您的程序员更好地掌握需求,它们也会更好。
如果您预先进行大设计,使用大量 UML,想要抽象数据库后端,并且您的架构师比您的 DBA 或程序员更好地掌握需求,那么成熟的 ORM 会更好。
然后是选项#4:使用所有这些。整个系统通常不仅仅是一个程序,虽然许多程序可能与同一个数据库通信,但它们都可以使用适合程序特定任务和成熟度级别的任何方法。也就是说:您从直接编码的 SQL 或 LINQ 开始,然后通过在 ORM 和存储过程中重构您认为它们有意义的地方来使程序成熟。