NHibernate Multiquery无需连接即可进行紧急加载 [英] NHibernate Multiquery for eager loading without joins

查看:74
本文介绍了NHibernate Multiquery无需连接即可进行紧急加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以使用多查询并具有两个hql查询,以返回两个不同的实体集,其中一组实体在另一组实体中使用,并且会话通过一级缓存对其进行修复"?

Is it possible to use a multiquery and have two hql queries returning two different sets of entities where one of the sets are used in the other and that the session "fixes" this via the first level cache?

例如场景(一个愚蠢的问题,可以通过加入来解决)

E.g. scenario (a dumb one and it could be solved with joins)

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

public class Booking
{
  ...
}

在执行具有两个hql的多准则后:

After executing a multicriteria with two hql's:

  1. 将所有房间归还 IsAvailible = true
  2. 返回所有预订的房间,该房间的房间可以预订
  1. returning all rooms where IsAvailible = true
  2. returning all bookings having a room that has a room that IsAvailible

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

when accessing a room from the result and its bookings I want them to be resolved from the second resultset via the firstlevel cache of the session and there by avoiding n+1.

推荐答案

通常来说,NHibernate可以使用缓存来组合"通过Multiquery执行的查询的结果.但是,应该注意的是,这通常仅适用于无限制地加载惰性集合的情况.

Generally speaking, NHibernate can use the cache to "combine" the results from queries executed through Multiquery. However, it should be noted that this usually only applies to cases where lazy collections are loaded with no restrictions whatsoever.

示例:

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.

If we comment out two of the three options and execute the code, we will see that only option 3 will prevent a N+1, the other two will still load the InvoiceDetails for each Invoice in the loop.

当然,这是一个非常简单的示例,很明显,也可以在没有基本查询的情况下执行选项3,并且仍然返回相同的结果,但是我希望您能理解.

Of course this is a very simple example and it is obvious that Option 3 could also be executed without the Base-query and still return the same result, but I hope you get the idea.

在我们加载两组不同的实体的情况下,即根类与选项1中的不同,这种组合"很可能行不通.

In the case where we load two different sets of entities, i.e. the root class is different as in Option 1, this "combining" will most likely not work.

对不起,如果我使用QueryOver而不是HQL,但适用相同的规则.

Sorry, if I used QueryOver instead of HQL, but the same rules apply.

这篇关于NHibernate Multiquery无需连接即可进行紧急加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆