【问题标题】:NHibernate Nested List QueryNHibernate 嵌套列表查询
【发布时间】:2014-09-12 15:45:20
【问题描述】:

我有以下型号

public class Customer 
{
    public virtual long Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Invoice> Invoices { get; set; }
    public virtual XDocument AlotOfData { get; set; }
}

public class Invoice
{
    public virtual long CustomerId { get; set; }
    public virtual long Id { get; set; }
    public virtual IList<LineItem> LineItems { get; set; }
    public virtual XDocument AlotOfData { get; set; }
}

public class LineItem
{
    public virtual long InvoiceId { get; set; }
    public virtual long Id { get; set; }
    public virtual double Amount { get; set; }
    public virtual XDocument AlotOfData { get; set; }
}

如果我只做一个普通的休眠查询来获得客户,它会如下所示。

long customerId = 1;
Customer customer = Session.QueryOver<Customer>().Where(x => x.Id == customerId).SingleOrDefault();

如果我的所有子集合的映射文件中有lazy="false",它将导致执行以下 Sql 查询

1 次查询以获取客户(仅从客户表中选择列)

1 次查询以获取该客户的所有发票(仅从发票表中选择列)

对 LineItems 表的 n 次查询(每个 Invoice 的一次查询仅从 LineItems 表中选择列)

我想知道的是如何保留当前正在执行的相同查询,而不是 nhibernate 对 LineItems 表进行 n 个单独的查询,它只会产生 1。有没有办法可以做到这一点通过 in 子句或连接到发票表,但不从发票表中选择列。

谢谢 杰里米

【问题讨论】:

标签: sql .net nhibernate


【解决方案1】:

是的 NHibernate 支持这个功能,它被称为:

19.1.5. Using batch fetching

让我从文档中引用:

NHibernate 可以有效地利用批量获取,也就是说,如果访问一个代理(或集合),NHibernate 可以加载多个未初始化的代理。批量获取是对惰性选择获取策略的优化。有两种方法可以调整批量获取:在类和集合级别。

类/实体的批量获取更容易理解。假设您在运行时有以下情况:您在一个 ISession 中加载了 25 个 Cat 实例,每个 Cat 都有一个对其所有者的引用,即一个 Person。 Person 类使用代理lazy="true" 进行映射。如果您现在遍历所有猫并在每个猫上调用 cat.Owner,NHibernate 将默认执行 25 个 SELECT 语句,以检索代理所有者。您可以通过在 Person 的映射中指定批量大小来调整此行为:

<class name="Person" batch-size="10">...</class>

NHibernate 现在将只执行三个查询,模式为 10、10、5。...

该设置 batch-size="25" 也可用于集合映射:

您还可以启用集合的批量获取。例如,如果每个 Person 都有一个 Cats 的惰性集合,并且当前在 ISesssion 中加载了 10 个 person,则遍历所有 person 将生成 10 个 SELECT,每次调用 person.Cats 一个。如果在 Person 的映射中开启 Cats 集合的批量抓取,NHibernate 可以预取集合:

<class name="Person">
    <set name="Cats" batch-size="3">
        ...
    </set>
</class>

我强烈建议使用它。我确实在每个类和集合上都有该映射

另见:

【讨论】:

  • 当您从父级访问子列表时,仅批处理组获取,我想要做的是从父级的子列表中获取所有子列表。不过谢谢
  • 事实上,在您的情况下,您的 1 + 1 + n 查询将被替换为 1 + 1 + 1 * (count/25)。这是显着的改进。事实上,这就是您可以通过 NHibernate 获得的
  • 所以我只需将 batch-Size="25" 放在我的订单项袋上?
  • 是的,先生!而已。令人惊讶的简单,令人难以置信的高效。但是收集上的映射是不够的——在你的&lt;class&gt;上做同样的事情......你玩的越多,你就会看到它可以为你做的越多...... (在收集上的映射就足够了,但是如果LinetItem 上会有一些many-to-one - 它不会发出n 个查询...)
  • 我正在尝试这个,我会告诉你结果如何。
猜你喜欢
  • 2021-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-29
  • 2019-05-05
  • 1970-01-01
  • 2023-04-09
相关资源
最近更新 更多