2011-12-09 12 views
17

Ho la seguente query:Come ordinare le collezioni bambino di entità in EF

public IEnumerable<Team> GetAllTeamsWithMembers(int ownerUserId) 
     { 
      return _ctx.Teams 
       .Include(x => x.TeamMembers) 
       .Where(x => x.UserId == ownerUserId) 
       .OrderBy(x => x.Name).ToList(); 

     } 

Come posso fare per ordinare le squadre con il loro nome, e quindi avere tutti i membri figlio di ogni squadra ordinati per loro nome?

Sembra che sia necessario creare una nuova classe DTO e utilizzare una selezione. Mi piacerebbe utilizzare le entità EF già create, in questo caso il team ha una proprietà di navigazione per i membri. Ritorna IEnumerable<Team> dal mio livello di repository.

Non sembra essere un modo ordinato di ordinare raccolte figli in EF. Qualcuno può aiutare?

+1

Ecco alcuni esempi: http://stackoverflow.com/a/7181574/270591, http://stackoverflow.com/a/7528266/270591, http://stackoverflow.com/a/7395406/270591 – Slauma

+0

possibile duplicazione di [EF 4.1 code-first: come ordinare le proprietà di navigazione quando si utilizzano metodi Includi e/o Seleziona?] (http://stackoverflow.com/questions/7522784/ef-4-1-code-first-how- to-order-navigation-properties-when-using-include-and-or) –

risposta

16

È possibile caricare i dati e ordinarli in memoria dopo averli caricati.

IEnumerable<Team> teams = _ctx.Teams 
      .Include(x => x.TeamMembers) 
      .Include(x => x.TeamMembers.Select(u => u.User)) 
      .Where(x => x.UserId == ownerUserId) 
      .OrderBy(x => x.Name).ToList(); 

foreach (var team in teams) 
{ 
    team.TeamMembers = team.TeamMembers.OrderBy(m => m.Name); 
    foreach (var teamMember in team.TeamMembers) 
    { 
     teamMember.Users = teamMember.Users.OrderBy(u => u.Name); 
    } 
} 

Oppure si potrebbe usare proiezioni e utilizzare il rilevamento delle modifiche di EF per ordinare la vostra collezione. Here is an example di filtrare un Include ma lo stesso funziona per l'Ordine.

+2

Grazie per questo, semplice ed efficace. Ho pensato che ci potrebbe essere qualcosa di un po 'più LINQish, non appassionato di loop ma fa il lavoro! – jaffa

2

Si potrebbe scaricare le vostre squadre e dei loro membri del team in un tipo anonimo (probabilmente non quello che volete), in questo modo:

public IEnumerable<Team> GetAllTeamsWithMembers(int ownerUserId) 
{ 
    return (from t in _ctx.Teams 
     where t.UserId == ownerUserId 
     select new { 
      Team = t, 
      TeamMembers = t.TeamMembers.OrderBy(m => m.Name) 
     }).ToList() 
} 

È possibile effettuare il ciclo poi attraverso di loro:

foreach(Team team in GetAllTeamsWithMembers(1234)) 
{ 
    string teamName = team.Team.Name; 
    string firstTeamMemberName = team.TeamMembers.First().Name; 
} 

Aggiornamento: Per la cronaca, la mia opinione è di non utilizzare questa soluzione, ma di ordinare ogni raccolta in un ciclo o durante il rendering/associazione.

Ho rimosso la seconda soluzione, poiché è stato rilevato che EF non può selezionare in entità.

+0

Purtroppo la seconda opzione non funziona perché LINQ to Entities non consente di proiettare in un'entità. – Slauma

+0

La prima opzione funziona se aggiungi un .Select (a => a.Team) dopo il ToList(). –

+0

@Slauma Non lo sapevo. –

Problemi correlati