2010-08-09 6 views
1

J'ai un référentiel qui accède à mon Entity Framework. J'ai une méthode qui ressemble à ceci:Comment écrire un Func <T, bool> pour retourner l'entité avec le plus grand nombre d'enfants?

public TEntity FindOne(Expression<Func<TEntity, bool>> criteria) 
{ 
    var query = _queryAll.Where(criteria); 
    return query.FirstOrDefault(); 
} 

J'ai 2 entités qui ont une relation de un à plusieurs. Appelons les Courses et Students. Un Course peut avoir plusieurs Students. J'aimerais écrire une requête qui renvoie le cours qui a le plus d'élèves. Mais comment écrire cela comme Func<T, bool>?

J'espère que ce n'est pas

(x=>x.OrderBy(y=>y.Students.Count()).FirstOrDefault().id == x.id) 

Parce que l'ajout d'un autre critère semble que cela ne fonctionnerait pas:

(x=>x.OrderBy(y=>y.Students.Count()) 
     .FirstOrDefault().id == x.id 
     && x.CourseName == "CS101") 

Répondre

2

Ce n'est pas du tout pourquoi vous mettriez le && x.Course == "CS101" à la fin. Qu'est-ce que cela veut dire? Je suspecte fortement le problème dans votre conception d'essayer de tout entasser dans une seule clause Where dans votre méthode FindOne. Tout simplement, tout ne peut pas facilement s'exprimer ainsi.

En outre, vous devriez utiliser OrderByDescending de sorte que le premier résultat a le le plus étudiants. En dehors de cela, l'utilisation de la commande me semble assez raisonnable en termes de requête globale - mais elle ne rentrera pas parfaitement dans votre schéma FindOne.

EDIT: Ceci est un problème plus important que le simple besoin de deux conditions. Vous pourrait écrire:

x => x.CourseId == "CS101" && 
    x.Students.Count() == Courses.Where(x => x.CourseId == "CS101")) 
            .Max(x => x.Students.Count()) 

... mais le problème est que, à ce moment-là, vous devez avoir accès à Courses de toute façon, que je vous imagine vous essayez de sortir de. En dehors de cela, il devrait travailler mais c'est grotesque.

Si vous pouvez avoir accès à des cours, vous pourriez aussi bien ignorer FindOne et écrire la requête vous:

var course = courses.Where(course => course.CourseId == "CS101") 
        .OrderByDescending(course => course.Students.Count()) 
        .FirstOrDefault(); 

C'est bien plus simple que la première version.

+0

merci pour le bug orderby - corrigé. Je suppose que ce dont je ne sais pas, c'est comment ajouter un second critère. Je pense que mon nom de propriété "Course" était confus et je ne l'ai pas lu - également corrigé. – itchi

+0

Merci .. Je suis venu ici parce qu'il semblait grotesque :) Je pense que c'est plus un échec avec mon dépôt (qui n'expose pas IQueryable) que tout. Peut-être que je pourrais ajouter un FindTopOne (Expression > critères, Expression > trier) – itchi