2010-11-29 5 views
1

Compte tenu des classes A et B oùLINQ to NHibernate - sélectionnez problème de comptage

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

class B 
{ 
string Name; 
} 

Avec la cartographie FluentNH, relation many-to-many qui est HasManyToMany (x => xB) pour A. B n'a pas référence à la version A. NH est 2.1.2.4000.

Quelle devrait être la requête linq pour sélectionner la collection où chaque ligne contient B.Name et le nombre de A contenant ce B? Le résultat doit être la liste des types anonymes avec deux champs: Nom et nombre. Le résultat devrait également inclure tous les B, donc il devrait être jointure externe.

Mon intention est d'obtenir le résultat avec des allers-retours minimaux à la base de données, peut-être en une seule fois.

+1

Quelle collection? Tableau de A, ou Tableau de B, ou IQueriable de quelque chose? Clearifiez votre question, s'il vous plaît) –

+0

S'il vous plaît inclure vos fichiers de cartographie? Utilisez-vous NH2.1.2 ou NH3? Votre première tentative d'interrogation LINQ vous aidera également à clarifier votre intention. –

+0

@The_Smallest et @James J'ai édité la question J'espère que cela aide. – rovsen

Répondre

3

Si vous voulez le faire dans LINQ en un seul coup dans le code, vous pouvez le faire ...

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) ne peut pas gérer un GroupBy après une SelectMany il semble, le premier ToList tire toutes les données en mémoire. C'est inefficace - un compte SQL serait mieux. Vous pouvez également ajouter une collection chargée paresseuse à votre classe B qui remonte à A. Si vous utilisez une table many-to-many au milieu, cela devrait être facile.

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

Votre requête devient simplement ...

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

qui produit SQL très efficace de Linq (en utilisant un compte) et donne le même résultat.

+0

merci pour la réponse. l'exigence est la jointure externe, tous les B de la table B. (J'ai édité la question car elle ne semblait toujours pas claire). mais je devine de votre dernière requête en supprimant où la clause fera cela. Je vais essayer de cette façon. – rovsen