2

マルチクエリを使用して、2つのhqlクエリが2つの異なるエンティティのセットを返し、一方のセットがもう一方のセットで使用され、セッションが第1レベルのキャッシュを介してこれを「修正」することは可能ですか?

例:シナリオ(ばかげたシナリオで、結合で解決できる可能性があります)

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

public class Booking
{
  ...
}

2つのhqlで多基準を実行した後:

  1. IsAvailible=trueであるすべての部屋を返す
  2. IsAvailibleの部屋がある部屋を持つすべての予約を返す

結果とその予約から部屋にアクセスするときは、セッションの第1レベルのキャッシュを介して、n + 1を回避することにより、2番目の結果セットからそれらを解決する必要があります。

4

2 に答える 2

7

一般的に、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つのオプションのうち2つをコメントアウトしてコードを実行すると、オプション3のみがN + 1を防止し、他の2つはループ内のInvoiceDetailsそれぞれのforをロードすることがわかります。Invoice

もちろん、これは非常に単純な例であり、オプション3をBaseクエリなしで実行しても同じ結果が返されることは明らかですが、理解していただければ幸いです。

2つの異なるエンティティのセットをロードする場合、つまりオプション1のようにルートクラスが異なる場合、この「結合」はほとんど機能しません。

申し訳ありませんが、HQLの代わりにQueryOverを使用した場合、同じルールが適用されます。

于 2011-04-12T13:00:19.017 に答える
0

ギュス、設定されていないために同様の問題が発生する場合があることに注意してください LeftOuterJoin

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

于 2015-03-18T17:09:47.327 に答える