2010-10-18 8 views
1

J'ai un modèle EntityFramework qui a une entité utilisateur qui a une EntityCollection d'organisations.Comment puis-je condenser la requête Linq suivante en une seule requête IQueryable?

Pour un utilisateur particulier, j'essaie d'écrire une requête Linq pour renvoyer les noms des organisations auxquelles l'utilisateur appartient où cette requête ne touchera qu'une seule fois la base de données.

Mon problème est que je ne vois pas comment écrire cette requête sans avoir à matérialiser d'abord l'utilisateur puis interroger la collection de l'organisation des utilisateurs.

Je voudrais essayer d'écrire une requête qui frappe une fois la DB.

Ce que j'ai jusqu'à présent:

var orgNames = context.Users 
    .Where(u => u.LoweredUserName == userName.ToLower()) 
    //materialises user 
    .FirstOrDefault() 
    .Organisations 
    //second hit to the db 
    .Select(o => o.Name); 

Ce que je psuedo visais mais ne peut pas voir le bois pour les arbres:

orgNames = context.Users 
    .Where(u => u.LoweredUserName == userName.ToLower()) 
    //don't materialise but leave as IQueryable 
    .Take(1) 
    //The problem: turn what the query sees as possibly multiple 
    // (due to the Take method) EntityCollection<Organisation> into a List<String> 
    .Select(u => u.Organisations.Select(o => o.Name)); 

J'ai regardé des agrégats mais il me semble aller en cercles :)

Répondre

2

Doh! Je pense que je peux répondre à ma propre question en utilisant SelectMany pour condenser la collection des collections dans une collection comme ceci:

orgNames = context.Users.Where(u => u.LoweredUserName == userName.ToLower()) 
       .Take(1) 
       .SelectMany(u => u.Organisations) 
       .Select(o => o.Name); 
0

Je suppose que Abaissé nom d'utilisateur est unique, sinon la requête serait assez vide de sens, donc vous pouvez simplement utiliser.

context.Users 
     .Where(u => u.LoweredUserName == userName.ToLower()) 
     .Select(u => u.Organisations.Select(o => o.Name)); 
Questions connexes