2011-07-11 7 views
0

私は三角形を形成する少し複雑なオブジェクトモデルを持っています。 Userエンティティは、ItemsTaxonomiesのコレクションを持ちます。 Itemにもタクソノミがあります。便宜上、ItemTaxonomyはそのオーナーを知り、TaxonomyItemと知りたいと思っていました。図を参照してください。NHibernate - 3つのクラス間の3つの双方向関係がN + 1を与えます

diagram

だから、これは3双方向の関係になります。私の問題は、そのようなNHibernateでそれをマップし、与えられたIDを持つユーザーを求めているとき、私はSelect N+1問題を取得しています。

最初にUserがロードされ、熱心にItemsが読み込まれます。その後、Taxonomiesは、それに接続された熱心に読み込まれたItemで読み込まれます。これは、期待通りに、マッピングで定義されているとおりです。しかし、Taxonomiesに関連するItemsを読み込むためのN + 1のクエリがあります。

queries

オブジェクトグラフのすべての部分が既にロードされたので、これは冗長です。 User-Itemリレーションシップを一方向(User)から(期待どおり2つしかありません)単方向にすると、問題は消えますが、その逆の関係を取り除きたくありません。 3つの関係すべてを双方向で最適なフェッチにすることは可能ですか?ここで

私のマッピングの部品です:

public class UserOverride : IAutoMappingOverride<User> 
{ 
    public void Override(AutoMapping<User> mapping) 
    { 
     mapping.HasMany(x => x.Items).Inverse() 
      .Not.LazyLoad().Fetch.Join(); 
     mapping.HasMany(x => x.Taxonomies).Inverse() 
      .LazyLoad().Fetch.Select(); 
    } 
} 

public class ItemOverride : IAutoMappingOverride<Item> 
{ 
    public void Override(AutoMapping<Item> mapping) 
    { 
     mapping.References(x => x.Taxonomy); // many-to-one 
    } 
} 

public class TaxonomyOverride : IAutoMappingOverride<Taxonomy> 
{ 
    public void Override(AutoMapping<Taxonomy> mapping) 
    { 
     mapping.HasOne(x => x.Item).PropertyRef(x => x.Taxonomy) 
      .Not.LazyLoad().Fetch.Join(); 
    } 
} 

そして、私は、できるだけ簡単な方法で自分のデータベースを照会:マッピングがすべてのクエリに影響しますので

var user = session.Get<User>(1); 

答えて

1

、私はそのルールで生きるのが好きエンティティが他のエンティティなしでは決して役に立たない場合にのみ、マッピングを熱心にロードするように変更する必要があります。あなたの状況では、ユーザーを欲しがってアイテムやタクソノミーの記録を気にすることができないならば、あなたは無益な特別なデータベース作業をするでしょう。

あなたの質問では、他のルート経由で熱心なロードを実行することをお勧めします。

Session.QueryOver<User>().Where(u => u.Id == 1) 
    .join.QueryOver<Items>(u => u.Items) 
    .Join.QueryOver<Taxonomy>(i => i.Taxonomy) 
    .TransformUsing(Trasnformers.DistinctRootEntity); 
+0

私は他のシナリオでは 'User'を使用しません。とにかく、結果は似ています。最初のクエリは必要なものすべてを結合し、2番目は 'Items'を別々に引っ張ります。もう一度' Items'にN + 1があります。 – NOtherDev

+0

テストの前にマッピングからレイジーローディング仕様を削除しましたか? –

+0

OK、クエリとマッピングバージョンの両方で実行されます。とにかく、なぜすべての値が既に分かっているのであれば、 'Taxonomy'の' Items'を読み込むための別のクエリを発行する必要があるのは不思議です... – NOtherDev