一般来说,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,其他两个仍然会在循环中加载InvoiceDetails
for each 。Invoice
当然这是一个非常简单的例子,很明显选项 3 也可以在没有 Base-query 的情况下执行并且仍然返回相同的结果,但我希望你明白这一点。
在我们加载两组不同实体的情况下,即根类与选项 1 中的不同,这种“组合”很可能不起作用。
抱歉,如果我使用 QueryOver 而不是 HQL,但同样的规则适用。