NHibernate Multiquery for eager loading without joins

纵饮孤独 提交于 2019-12-03 08:57:49

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.

Examples:

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;
}

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.

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.

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.

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

Gyus, keep in mind that sometimes you can have similar problems because of LeftOuterJoin is not set.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!