Vous pouvez le faire efficacement dans une seule requête, la grammaire est simplement maladroite :
var groups = await db.Parents
.Where(p => p.Id == id)
.Select(p => new
{
P = p,
C = p.Children.OrderBy(c => c.SortIndex)
})
.ToArrayAsync();
// Query/db interaction is over, now grab what we wanted from what was fetched
var model = groups
.Select(g => g.P)
.FirstOrDefault();
Explication
note asynchrone
Il se trouve que j'ai utilisé le async
extensions ici, que vous devriez probablement utiliser, mais vous pouvez vous débarrasser des await
/ async
si vous avez besoin d'une requête synchrone sans nuire au tri efficace des enfants.
Premier morceau
Par défaut, tous les objets EF récupérés dans la Db sont "suivis". De plus, l'équivalent d'EF en SQL Select
est conçu autour des objets anonymes, que vous nous voyez sélectionner ci-dessus. Lorsque l'objet anonyme est créé, les objets assignés à l'objet anonyme sont supprimés. P
y C
sont toutes deux suivies, ce qui signifie que leurs relations sont notées et que leur état est maintenu par l'outil de suivi des changements EF. Depuis C
est une liste d'enfants dans P
même si vous ne leur avez pas demandé explicitement d'être liés dans votre objet anonyme, EF les charge de toute façon comme cette collection d'enfants, en raison de la relation qu'il voit dans le schéma.
Pour en savoir plus, vous pouvez décomposer la requête ci-dessus en deux requêtes distinctes, en chargeant uniquement l'objet parent, puis uniquement la liste des enfants, dans des appels Db complètement différents. L'outil de suivi des changements EF remarquera et chargera les enfants dans l'objet parent pour vous.
Second morceau
Nous avons piégé EF pour qu'il nous rende les enfants commandés. Maintenant, nous saisissons juste l'objet Parent - ses enfants seront toujours attachés dans l'ordre, comme nous le voulions.
Nulles et tables comme ensembles
Il y a une étape maladroite en deux temps, principalement pour des raisons de bonnes pratiques concernant les valeurs nulles ; elle est là pour faire deux choses :
En d'autres termes, le dernier morceau aurait pu être.. :
var model = groups.First().P;
Mais si l'objet n'est pas présent dans la base de données, une exception de référence nulle sera générée. C# 6 introduira une autre alternative, l'opérateur de coalescence des propriétés nulles. - donc dans le futur vous pourriez remplacer le dernier morceau par :
var model = groups.FirstOrDefault()?.P;