2010-11-29 13 views
1

die Klassen A und B gegeben, in demLinq to NHibernate - select count Problem

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

class B 
{ 
string Name; 
} 

Mit FluentNH Mapping, Beziehung many-to-many ist die HasManyToMany (x => xB) ist für A. B hat keine Verweis auf A. NH-Version ist 2.1.2.4000.

Was sollte die linq-Abfrage sein, um die Sammlung auszuwählen, in der jede Zeile B.Name und die Anzahl der A enthält, die B enthalten? Ergebnis muss die Liste des anonymen Typs sein, die 2 Felder hat: Name und Anzahl. Ergebnis sollte auch alle B enthalten, daher sollte es Outer Join sein.

Mein Ziel ist es, das Ergebnis mit minimalen Round-Trips zur Datenbank zu bekommen, möglicherweise auf einmal.

+1

Was sammeln? Array von A oder Array von B oder IQueriable von etwas? Bitte klären Sie Ihre Frage bitte) –

+0

Bitte fügen Sie Ihre Zuordnungsdateien hinzu? Verwenden Sie NH2.1.2 oder NH3? Ihr erster Versuch mit Ihrer LINQ-Abfrage würde auch dazu beitragen, Ihre Absicht zu verdeutlichen. –

+0

@The_Smallest und @James Ich habe die Frage bearbeitet, ich hoffe, es hilft. – rovsen

Antwort

3

Wenn Sie es in Linq in einem Treffer in Code tun möchten, können Sie dies tun ...

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) kann ein nicht umgehen GroupBy nach einer SelectMany es scheint, so die erste ToList zieht alle Daten in den Speicher. Dies ist ineffizient - eine SQL-Zählung wäre besser.

Alternativ können Sie eine lazy loaded-Sammlung zu Ihrer B-Klasse hinzufügen, die auf A zurückgeht. Wenn Sie eine Viele-zu-Viele-Tabelle in der Mitte verwenden, sollte das einfach sein.

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

Ihre Anfrage einfach wird ...

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

die sich von Linq (unter Verwendung einer Zählung) und das gleiche Ergebnis sehr effizient SQL erzeugt.

+0

danke für die Antwort. die Voraussetzung ist Outer Join, alle B's aus Tabelle B. (Ich habe die Frage bearbeitet, da sie immer noch nicht kristallklar erschien). aber ich denke, dass von der letzten Abfrage entfernt where-Klausel das tun wird. Ich werde es versuchen. – rovsen