2010-11-29 19 views
1

は、クラスAとFluentNHマッピングでLINQの - 選択カウント問題

class A 
{ 
string Name; 
Ilist<B> BList; 
} 

class B 
{ 
string Name; 
} 

Bを考えると、の関係は、A BのHasManyToMany(X =>のxB)多対多であるれている持っていませんA. NH版への参照は2.1.2.4000です。

何各行はB.NameとAさんはそのBを含むのカウントを格納するコレクションを選択するためにLINQクエリをすべきですか?結果は、名前とカウントの2つのフィールドを持つ匿名タイプのリストでなければなりません。結果にはすべてのBを含める必要があります。したがって、外部結合である必要があります。

私つもりはおそらく一度に、データベースへの最小のラウンドトリップで結果を得ることです。

+1

どのような回収ですか? Aの配列、Bの配列、または何かのIQueriable?あなたの質問を明確にしてください) –

+0

マッピングファイルを含めてください。 NH2.1.2またはNH3を使用していますか? LINQクエリでの最初の試みは、あなたの意図を明確にするのにも役立ちます。 –

+0

@ The_Smallestと@James質問を編集しました。 – rovsen

答えて

3

あなたは、コード内の1本のヒットでLINQの中でそれをしたい場合は、あなたがこれを行うことが...

var result = Session.Linq<A>() 
    .SelectMany(a => a.BList, (a, b) => new { b.Name, A = a.Id }) 
    .ToList() 
    .GroupBy(x => x.Name) 
    .Select(x => new { Name = x.Key, Count = x.Count() }) 
    .ToList(); 

NHibernate.Linq(2.1.2.4000)は、それが思わSelectManyGroupByを扱うことができません、最初のToListはすべてのデータをメモリにプルします。これは非効率的です--SQLの数がより良いでしょう。

また、Bクラスに遅延ロードされたコレクションを追加して、Aに戻すこともできます。途中で多対多のテーブルを使用している場合、それは簡単なはずです。

public class B 
{ 
    public virtual string Name { get; set; } 
    public virtual IList<A> AList { get; private set; } 
} 

あなたのクエリは、単に... LINQの(カウントを使用して)から、非常に効率的なSQLを生成し、同じ結果を与える

var result = Session.Linq<B>() 
    .Where(b => b.AList.Count > 0) 
    .Select(b => new { b.Name, b.AList.Count } 
    .ToList(); 

になります。

+0

要件は外部結合であり、すべてのBはテーブルBからです(私は依然としてクリスタルではないように編集しました)。しかし、私はあなたの最後のクエリからwhere句を削除すると思います。私はそのようにします。 – rovsen