EF LINQ inclut des entités multiples et imbriquées
Ok, j'ai des entités à trois niveaux avec la hiérarchie suivante: Course -> Module - > Chapter
Voici la déclaration EF LINQ originale:
Course course = db.Courses
.Include(i => i.Modules.Select(s => s.Chapters))
.Single(x => x.Id == id);
Maintenant, je veux inclure une autre entité appelée Lab qui est associée à un cours.
Comment puis-je inclure L'entité Lab?
J'ai essayé ce qui suit, mais cela n'a pas fonctionné:
Course course = db.Courses
.Include(i => i.Modules.Select(s => s.Chapters) && i.Lab)
.Single(x => x.Id == id);
Des idées sur l'inclusion de la 2ème entité?
Tout conseil ou information serait très apprécié. Merci!
5 réponses
Avez-vous essayé d'ajouter un autre Include
:
Course course = db.Courses
.Include(i => i.Modules.Select(s => s.Chapters))
.Include(i => i.Lab)
.Single(x => x.Id == id);
Votre solution échoue car Include
ne prend pas un opérateur booléen
Include(i => i.Modules.Select(s => s.Chapters) && i.Lab)
^^^ ^ ^
list bool operator other list
Mise à Jour Pour en savoir plus, téléchargez LinqPad et parcourez les exemples. Je pense que c'est le moyen le plus rapide de se familiariser avec Linq et Lambda.
Comme un début - la différence entre Select
et Include
est que cela avec un Select vous décidez quoi vous voulez revenir (aka projection). Le Inclure est un Chargement impatient fonction, qui indique Entity Framework que vous voulez qu'il inclue des données provenant d'autres tables.
La syntaxe Include peut également être en chaîne. Comme ceci:
db.Courses
.Include("Module.Chapter")
.Include("Lab")
.Single(x => x.Id == id);
Mais les échantillons de LinqPad expliquent mieux cela.
Include
est une partie de l'interface fluide, de sorte que vous pouvez écrire plusieurs Include
déclarations suivantes d'autres
db.Courses.Include(i => i.Modules.Select(s => s.Chapters))
.Include(i => i.Lab)
.Single(x => x.Id == id);
Vous pouvez également essayer
db.Courses.Include("Modules.Chapters").Single(c => c.Id == id);
Dans Entity Framework Core (EF.core
), Vous pouvez utiliser .ThenInclude
pour inclure les niveaux suivants.
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ToList();
Plus d'informations: https://docs.microsoft.com/en-us/ef/core/querying/related-data
Remarque:
Dites que vous avez besoin de plusieurs ThenInclude()
sur blog.Posts
, répétez simplement le Include(blog => blog.Posts)
et faites un autre ThenInclude(post => post.Other)
.
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.Include(blog => blog.Posts)
.ThenInclude(post => post.Other)
.ToList();
On peut écrire une méthode d'extension comme ceci:
/// <summary>
/// Includes an array of navigation properties for the specified query
/// </summary>
/// <typeparam name="T">The type of the entity</typeparam>
/// <param name="query">The query to include navigation properties for that</param>
/// <param name="navProperties">The array of navigation properties to include</param>
/// <returns></returns>
public static IQueryable<T> Include<T>(this IQueryable<T> query, params string[] navProperties)
where T : class
{
foreach (var navProperty in navProperties)
query = query.Include(navProperty);
return query;
}
Et l'utiliser comme ceci même dans une implémentation Générique:
string[] includedNavigationProperties = new string[] { "NavProp1.SubNavProp", "NavProp2" };
var query = context.Set<T>()
.Include(includedNavigationProperties);