代码之家  ›  专栏  ›  技术社区  ›  Jorge Córdoba

ORMs的当前状态是什么?

  •  2
  • Jorge Córdoba  · 技术社区  · 17 年前

    我的理由一直是,这是一个非常容易泄露的抽象概念。。。主要是因为SQL提供了一种非常强大的方法,可以从关系源检索数据,而关系源通常会被ORM搞得一团糟,因此您会损失很多性能,从而使您看起来没有关系后端。

    我一直认为数据应该始终保存在数据库中,而不是占用无论如何都无法扩展的应用程序内存。此外,通用的性能打击是有害的。例如,如果我需要数据库中所有客户机的名称和地址,SQL为我提供了一种简单的方法,可以在一个查询中获得它。使用ORM,我需要获取所有客户机,然后获取每个名称和地址,即使是惰性加载,也需要更长的时间。

    我是这么想的,但是上面有什么改变吗?我看到很多ORM,比如实体框架、NHibernate等等,它们最近似乎很流行。。。他们值得吗?他们解决了我上面描述的问题吗??

    4 回复  |  直到 17 年前
        1
  •  6
  •   Cœur Gustavo Armenta    7 年前

    All Abstractions Are Failed Abstractions

    IMHO ORM为您提供即时且巨大的开发速度提升。这就是为什么它们如此受欢迎。正确使用它们并不会让你陷入困境。始终可以手动调整性能。

    尽管Jeff专注于LinqtoSQL,但他所说的抽象和性能对NHibernate同样适用(我从多年的实际应用程序开发中了解到这一点)。我认为默认情况下应该使用ORM,因为它们在臭名昭著的90%的情况下都足够快。阅读为ORM编写的代码通常更具可维护性和可读性,尤其是当您的代码被继承您的代码的下一个开发人员拾取时。 Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live. 永远不要忘记那个家伙!

    此外,它们还提供现成的缓存、延迟加载、工作单元。。。你说吧。我发现当我对ORM的性能不满意时 是我的错

        2
  •  1
  •   Dan Rosenstark    17 年前

    抽象是有漏洞的,开发人员总是可以根据需要使用SQL。即使您不直接使用SQL,也必须考虑数据库命中的数量,等等。例如,在ActiveRecord中,“急切加载”用于避免多次数据库命中,因此您会看到类似的内容(包括初始查询中每篇文章的相关“作者”字段……我认为它在引擎盖下进行连接)

    for post in Post.find(:all, :include => :author)
    

    关键是抽象和所有抽象一样都会泄漏,但这不是真正的重点。要决定是否使用抽象,您必须考虑它是否会增加或减少您的一般工作负荷。换句话说,,

    我认为有效的抽象是那些成熟的: ActiveRecord已经在块中运行了一吨(Hibernate也是如此),因此它提供了一个 修补您通常会担心的大多数泄漏的方法,而无需显式地滚动您自己的低级解决方案(即,无需编写SQL)。

    除了学习曲线之外,我认为ORMs对于大多数数据库访问来说都是一个惊人的省时工具,而且大多数应用程序实际上都非常“正常”地使用数据库。尽管这可能不是您的情况,但避免直接访问数据库的ORM通常是一种早期且不必要的优化。

    编辑: 我没见过这个,但杰夫的名言是

    这个抽象是否使我们的代码 懂排除故障?是吗 我们没有它?

        3
  •  1
  •   Ants Aasma    17 年前

    一些更现代的ORM是真正强大的工具,可以解决许多现实世界的问题。好的ORM不会试图对您隐藏关系模型,而是实际上利用它使OO编程更加强大。它们实际上不是抽象,因为它们让您忽略了关系代数的“低级”细节,相反,它们是工具包,可以让您在关系模型上构建抽象,并使您更容易将数据引入命令式模型,跟踪更改并将其推回数据库。SQL语言确实没有提供任何好的方法来将公共谓词分解成可组合、可重用的组件,以实现businesstule级别的抽象。

    当然,性能会受到影响,但这主要是一个固定因素,因为您可以使ORM问题与SQL问题相同。比如你的名字和地址,在SQLAlchemy中你只需要

    for name, address in session.query(Client.name, Client.address):
        # process data
    

    你完成了。但是ORM帮助您的地方是当您拥有可重用的关系和谓词时。例如,假设您定义了一种连接到客户喜爱的项目的方法,并定义了一个谓词来查看该项目是否在销售中。然后,您可以通过以下查询获取一些他们最喜爱的商品在售的客户列表,同时还可以获取指定的销售人员:

    potential_sales = (session.query(Client).join(Client.favorite_items)
                      .filter(Item.is_on_sale)
                      .options(eagerload(Client.assigned_salesperson)))
    

    至少对我来说,这样编写查询的目的要快得多,更清晰,更容易理解,而不是十几行SQL。

        4
  •  0
  •   Yngve Sneen Lindal    17 年前

    至于任何抽象,您必须以性能或泄漏的形式支付。我同意你反对ORM,因为SQL是一种干净优雅的语言。我已经写了一些自己的小框架来为我做这些事情,但是嘿,然后我坐在那里用我自己的ORM(但是比Hibernate更能控制它)。Hibernate背后的人说它很快。它应该能够针对您的数据库完成大约95%的枯燥工作(简单的查询、更新等),但如果您愿意,它可以让您自由地完成最后5%的工作(在特殊情况下,您始终可以编写自己的映射)。

    我认为,大多数流行源于许多程序员都很懒惰,希望建立的框架为他们做肮脏无聊的持久性工作(我可以理解),但抽象的代价总是存在的。我会仔细考虑我的选择,然后选择在一个严肃的项目中使用ORM。