2010-12-15 172 views
6

J'ai une collection d'employés, et chaque employé a une collection de responsabilités. Je voudrais afficher une liste des employés triés par nom et publier leurs responsabilités, triés par titre.Comment commander une collection et sa sous-collection en utilisant LINQ?

Ainsi, il devrait être émis comme ceci:


Jane Jones

Responsabilités:

Responsabilité A

Responsabilité B

Mike Smith

Responsabilités:

Responsabilité A

Responsabilité C


Pour obtenir la collection initiale que j'utilise:

var employees = _context.Employees.OrderBy(e => e.Name); 

mais je ne peux pas à comprendre comment commander la sous-collection Responsabilités également. J'utilise MVC et mon View reçoit une collection Employee fortement typée, donc je ne veux pas générer et renvoyer un type anonyme.

+0

J'ai décidé de ne pas commander le colelction quand je la tire de la base de données. Techniquement la commande fait partie de la présentation, donc je le fais maintenant dans la vue (j'utilise MVC). Je commande maintenant la sous-collection quand je fais un foreach sur l'employé. Responsabilités. –

+0

Serait bien de savoir comment faire cela pour référence future cependant. Merci! –

+0

J'ai ajouté la 2ème approche .. Désolé, c'est assez lourd aussi. Je ne pense pas qu'il y ait un moyen plus facile, donc je suis d'accord avec vous - il serait préférable de faire des commandes dans la vue ou de créer un DTO (Data Transfer Object) spécial et de faire une projection dedans puis passer à la vue au lieu de l'employé. –

Répondre

2

1ère approche: (ne convient que pour LINQ à des objets ayant des responsabilités définies comme IList)

Vous pouvez copier dans une nouvelle collection d'employés, mais cela signifie que vous avez besoin de re-copie chaque champ dans de nouveaux employés, quelque chose comme ceci:

var employees = from e in _context.Employees 
       orderby e.Name 
       select new Employee 
       { 
        Name = e.Name, 
        ...re-assign other properties... 
        Responsibilities = e.Responsibilities.OrderBy(r => r.Name).ToList() 
       }; 

2ème approche:

Utilisation du DataLoadOptions. Fondamentalement, vous créez un objet DataLoadOptions qui spécifie comment commander une relation particulière, donc dans votre cas:

var options = new DataLoadOptions(); 
options.AssociateWith<Employees>(e => e.Responsibilities.OrderBy(r => r.Name)); 
_context.LoadOptions = options; 

var employees = _context.Employees.OrderBy(e => e.Name); 

Les responsabilités seront commandés automatiquement.

+0

Je pense aussi que c'est une perte de recopier chaque champ. En réalité, lorsque j'essaie cela, j'obtiens une erreur que je ne peux pas convertir un objet de IQueryable en EntityCollection. Donc ça ne marche pas pour moi. –

+0

oui, il doit être converti en EntitySet vs Liste .. plus vous ne pouvez pas créer un nouvel employé dans la requête b/c L2S ne permet pas cela, il semble donc que seule la 2ème option peut être utilisée dans votre scénario. –

3

Vous pouvez faire quelque chose comme:

var employees = _context.Employees.OrderBy(e => e.Name); 
employees.ToList().ForEach(e => e.Responsibilities = e.Responsibilities.OrderBy(r => r.Name)); 
+0

Lorsque j'essaie ceci, j'obtiens l'erreur: Impossible de convertir le type de source IOrderedEnumerable <> en type cible EntityCollection <>. –

+0

A travaillé pour moi. Je ne suis pas sûr que ce soit le meilleur moyen pour mon cas particulier mais pour l'instant je m'en tiendrai à ça. – Jeroen

+0

Pour une personne qui obtient une erreur en tant que 'Impossible de convertir le type de source IOrderedEnumerable <> en type cible EntityCollection <>'. Vous juste le convertir en liste à savoir. 'employees.ToList(). ForEach (e => e.Responsibilities = e.Responsibilities.OrderBy (r => r.Name) .ToList())' –