2009-06-02 13 views
24

ルートエンティティを読み込み、子コレクションと集約メンバのすべてを読み込みたいと思います。NHibernateで子コレクションを読み込むことを熱心におこなう

FluentNHibernateでSetFetchModeを使用しようとしましたが、3レベルの深さがあるため、子コレクションの1つに重複があります。 DistinctRootEntityResultTransformerは残念ながらルートの重複だけを削除します。

return Session.CreateInvoiceBaseCriteria(query, archived) 
    .AddOrder(new Order(query.Order, query.OrderType == OrderType.ASC)) 
    .SetFetchMode("States", FetchMode.Eager) 
    .SetFetchMode("Attestations", FetchMode.Eager) 
    .SetFetchMode("AttestationRequests", FetchMode.Eager) 
    .SetFetchMode("AttestationRequests.Reminders", FetchMode.Eager) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
    .List<Invoice>(); 

これをアーカイブするには複数のクエリなどを使用できますか?

さらに、このアプローチではデータベースから不必要に大きな結果セットが得られないでしょうか?

提案がありますか?

答えて

0

それはあなたが、私はこの記事を見て勧めを探している正確に何ではないかもしれませんが:

Eager loading aggregate with many child collections

あなたがそのサイトの残りの部分を見て回る場合は、議論にも多くの記事があります熱心なロードや他の素晴らしいnHibernateのもの。

+2

確かにいい記事ですが、自分の状況に適用できるかどうかは不明です。特定のルートエンティティを読み込むことについて熱心な記事で説明されている解決策、私の問題は、ルートエンティティのコレクションを熱心にロードしたいということです。 MultiCriteraを使用する場合は、特定のエンティティを指定せずにすべての異なるクエリを接続する方法を見つける必要があります。どのようにそれを行うことができます提案? – Kristoffer

+0

この例では階層レベルは1つしかありませんが、孫がいないため、MultiQuery/MultiCriteriaはあまり役に立たないようです。後のクエリはクエリ#1のように以前のクエリの結果を参照できないためです。 where ... ...クエリー#2:c)にparentがある孫gを選択します。 –

8

解決策が見つかりましたが、それほど美味しくありません。最初に、すべての請求書IDを見つけて、次にそれらをマルチクエリで使用し、最後にHashedSetを介して結果をフィルタリングします。アイテムの数が多いため、通常のRestriction.Inを使用できず、文字列として強制的に送信されました。

おすすめの調整方法はありますか?

var criteria = Session.CreateInvoiceBaseCriteria(query, archived) 
    .SetProjection(Projections.Id()); 

var invoiceIds = criteria.List<int>(); 
if (invoiceIds.Count > 0) 
{ 
    var joinedIds = JoinIDs(criteria.List<int>()); // To many ids to send them as parameters. 

    var sql1 = string.Format("from Invoice i inner join fetch i.States where i.InvoiceID in ({0}) order by i.{1} {2}", joinedIds, query.Order, query.OrderType.ToString()); 
    var sql2 = string.Format("from Invoice i inner join fetch i.AttestationRequests where i.InvoiceID in ({0})", joinedIds); 
    var sql3 = string.Format("from Invoice i inner join fetch i.Attestations where i.InvoiceID in ({0})", joinedIds); 

    var invoiceQuery = Session.CreateMultiQuery() 
     .Add(sql1) 
     .Add(sql2) 
     .Add(sql3); 

    var result = invoiceQuery.List()[0]; 

    return new UniqueFilter<Invoice>((ICollection)result); 
} 

return new List<Invoice>(); 
+0

これは奇妙ですが、アテステーションは単一のクエリとしてフェッチされます。 – Kristoffer

+0

+1、これは実際に(そして残念ながら)これを達成するための最良の方法(パフォーマンス上の措置)です。 –

+0

私は似たような状況にあります(一度に3つのレベルを引き出そうとしています)。あなたのソリューションは重複を取り除きますが、深さは2レベルしかないようです。あなたの元の質問には、あなたの答えに含まれていない "AttestationRequests.Reminders"と呼ばれる第3レベルのダウンが含まれていました。 – MylesRip

2

あなたの質問に答えるには:はい、巨大な結果が得られます。

私がお勧め:

  • ただ単純に、熱心に特定の場所で
  • を取得せずに、あなたのクエリを記述フェッチ熱心を入れて、一つだけのクエリ
  • あたりあなたが本当にこれを使用し、パフォーマンスの問題を取得する場合インデックスを使用して解決できない、またはクエリとマッピング戦略を強化することができない場合は、複数のクエリでソリューションを使用します。
関連する問題