【问题标题】:NHibernate Multiquery for eager loading without joinsNHibernate Multiquery 无需连接即可快速加载
【发布时间】:2011-04-12 11:33:20
【问题描述】:

是否可以使用多查询并让两个 hql 查询返回两组不同的实体,其中一组在另一组中使用,并且会话通过一级缓存“修复”这个问题?

例如场景(一个愚蠢的场景,可以通过连接来解决)

public class Room
{
  ...
  public virtual ISet<Bookings> Bookings {get;set;}
  public virtual bool IsAvailible {get;set;}
  ...
}

public class Booking
{
  ...
}

使用两个 hql 执行多条件后:

  1. 返回所有房间 IsAvailible = true
  2. 返回所有房间的预订,该房间的房间有可用的房间

从结果及其预订访问房间时,我希望通过会话的一级缓存从第二个结果集中解决它们,并避免 n+1。

【问题讨论】:

    标签: nhibernate multi-query


    【解决方案1】:

    一般来说,NHibernate 可以使用缓存来“组合”通过 Multiquery 执行的查询的结果。但是,应该注意的是,这通常只适用于加载惰性集合时没有任何限制的情况。

    例子:

    Invoice iAlias = null;
    InvoiceDetails idAlias = null;
    
    // Base-Query: get Invoices with certain condition
    var invoices = session.QueryOver<Invoice>()
        .Where(i => i.Number == "001")
        .Future<Invoice>();
    
    // Option 1: this will still cause N+1 if we iterate through invoices,
    // because it doesn't know better
    var invoicedetails = session.QueryOver<InvoiceDetails>()
        .JoinAlias(a => a.Invoice, () => iAlias)
        .Where(() => iAlias.Number == "001")
        .Future<InvoiceDetails>();
    
    // Option 2: this will still cause N+1 if we iterate through invoices,
    // because we limited the possible results using a where-condition
    var invoices2 = session.QueryOver<Invoice>()
        .Left.JoinAlias(i => i.Details, () => idAlias)
        .Where(i => i.Number == "001")
        .And(() => idAlias.Quantity > 5)
        .Future<Invoice>();
    
    // Option 3: this will work without N+1, because we don't use a filter
    // -> NHibernate will use the collection in cache
    var invoices3 = session.QueryOver<Invoice>()
        .Left.JoinAlias(i => i.Details, () => idAlias)
        .Where(i => i.Number == "001")
        .Future<Invoice>();
    
    foreach (Invoice i in invoices)
    {
        int count = i.Details.Count;
    }
    

    如果我们注释掉三个选项中的两个并执行代码,我们会看到只有选项 3 会阻止 N+1,另外两个仍然会为循环中的每个 Invoice 加载 InvoiceDetails。

    当然这是一个非常简单的例子,很明显选项 3 也可以在没有 Base-query 的情况下执行,仍然返回相同的结果,但我希望你明白。

    在我们加载两组不同实体的情况下,即根类与选项 1 中的不同,这种“组合”很可能不起作用。

    抱歉,如果我使用 QueryOver 而不是 HQL,但适用相同的规则。

    【讨论】:

      【解决方案2】:

      Gyus,请记住,有时您可能会遇到类似的问题,因为 LeftOuterJoin 未设置。

      .JoinAlias(x => x.Prop, () => propAlias, JoinType.LeftOuterJoin)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-09
        • 2018-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多