【问题标题】:NHibernate: Solving N+1 in master-detail where detail has many-to-one relationship?NHibernate:在细节具有多对一关系的主细节中解决 N+1?
【发布时间】:2012-04-30 05:56:13
【问题描述】:

我有一个包含 OrderLines 集合的订单。每个 OrderLine 都有一个多对一的产品。对于所有订单,我有一个搜索窗口——默认情况下——在网格中显示所有订单。使用同一个窗口,我可以过滤包含给定产品的所有订单。我们的客户每天产生大约 700 个订单,订单平均有大约 35 行。

在搜索窗口中,我只显示存储在 Order 对象本身中的信息。但是,如果我过滤特定的产品,它将初始化我与 OrderLine 集合的延迟加载关系以及我的 OrderLine 中与我的产品的多对一关系。每个订单行逐行查询,每一行对产品表都有单独的查询。

所以平均每个订单我得到 35 个查询来初始化所有 OrderLine,加上 35 个查询来获取与该订单相关的产品。

一次加载所有订单行及其相关产品(如果不可能,每个订单的所有订单行)的最佳方式是什么?我知道我可以将我的多对一映射到 orderline 中的产品作为 fetch="join",但这仍然会给我留下 35 个单个查询来获取 orderlines+products。

仅供参考:目前我加载所有内容都是懒惰的。

有什么建议吗?我可以在这里使用 Future 吗?

问候,泰德

【问题讨论】:

    标签: nhibernate query-optimization lazy-loading eager-loading


    【解决方案1】:

    您的batch-size 设置为什么?

    保持延迟加载不变,在两个集合映射上将其设置为 35,这应该会将 1 + 35 + 35 个查询减少到 1 + 1 + 1。

    <bag ... batch-size='35' ..> 
    

    正如 Stefan 所指出的,您还需要在类上设置 batch-size='35'

    【讨论】:

    • 建议同意,但计算不正确。它将 1 + 35 + 35 减少到 1 + 1 + 1,但前提是您还要在产品类上指定批量大小。
    • 啊,好的,感谢 Stefan,这是因为他要进行多对一,对吗?
    • 是的,使用many-to-one时,需要在class上指定batch-size。
    【解决方案2】:

    在这种情况下,我不会检索订单实体本身。 我将创建一个“视图”类,并通过使用 NHibernate 项目,我将返回那些仅包含您感兴趣的信息的“视图”类,并将其放在概览表单或页面中。 搜索时,您可以执行一个新查询(仅一个),检索您感兴趣的“OrderView”实例。

    当您想要编辑订单或查看其详细信息时,我会加载实体。

    【讨论】:

    • 我不能延迟加载订单,因为我需要过滤产品,所以我必须获取所有行,并且每行都是产品,然后我可以过滤 ProductCode 属性。我可能错过了你的观点:)
    • 搜索/过滤时,我会使用 NHibernate 重新查询数据库,并且通过使用投影,并非所有产品都需要检索。
    【解决方案3】:

    您是否对加载的实体在内存中进行过滤操作?通常,您只想对那些包含相关产品订单行的订单执行查询。因此,您只需要根据查询结果填充您的窗口。无需遍历所有订单和所有订单行来填充仅包含一小部分数据的窗口。

    在数据库服务器上进行过滤通常比从服务器获取所有数据并在 C# 中进行过滤要快得多。

    您的描述对我来说并不完全清楚:鉴于您已经过滤了要显示的订单,您是否需要访问订单行和产品?
    - 如果没有,您可以使用上述解决方案。
    - 如果是,您可以对过滤后的订单查询进行连接提取,以直接将订单行与订单一起加载。连接获取不仅适用于 ,也适用于 ,因此您可以一次加载一些根实体及其子实体。如果根实体有很多很多列和多个子实体,则存在一些缺点,因为查询会为每个子实体冗余地检索根实体的数据。然而,在许多情况下(取决于整体系统配置)连接获取的好处远远超过成本。

    在您查询数据并且事先不清楚以下代码实际需要哪些数据的情况下,使用批量选择(使用 )可以帮助大幅减少数据库往返次数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-01
      相关资源
      最近更新 更多