简体   繁体   English

EF LINQ 包括多个和嵌套的实体

[英]EF LINQ include multiple and nested entities

Ok, I have tri-leveled entities with the following hierarchy: Course -> Module -> Chapter好的,我有具有以下层次结构的三级实体:课程->模块->章节

Here was the original EF LINQ statement:这是原始的 EF LINQ 语句:

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters))
                .Single(x => x.Id == id); 

Now, I want to include another entity called Lab which is associated with a course.现在,我想包含另一个与课程相关联的名为 Lab 的实体。

How do I include the Lab entity?如何包含 Lab 实体?

I tried the following but it didn't work:我尝试了以下但没有奏效:

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters) && i.Lab)
                .Single(x => x.Id == id); 

Any ideas on including the 2nd Entity?关于包括第二个实体的任何想法?

Any piece of advise or information would be highly appreciated.任何建议或信息将不胜感激。 Thanks!谢谢!

Have you tried just adding another Include :您是否尝试过添加另一个Include

Course course = db.Courses
                .Include(i => i.Modules.Select(s => s.Chapters))
                .Include(i => i.Lab)
                .Single(x => x.Id == id);

Your solution fails because Include doesn't take a boolean operator您的解决方案失败,因为Include不采用布尔运算符

Include(i => i.Modules.Select(s => s.Chapters) &&          i.Lab)
                           ^^^                  ^             ^ 
                          list           bool operator    other list

Update To learn more, download LinqPad and look through the samples.更新要了解更多信息,请下载LinqPad并查看示例。 I think it is the quickest way to get familiar with Linq and Lambda.我认为这是熟悉 Linq 和 Lambda 的最快方法。

As a start - the difference between Select and Include is that that with a Select you decide what you want to return (aka projection).首先 - SelectInclude之间的区别在于,使用 Select 您可以决定返回的内容(也称为投影)。 The Include is a Eager Loading function, that tells Entity Framework that you want it to include data from other tables. Include 是一个Eager Loading函数,它告诉 Entity Framework 您希望它包含来自其他表的数据。

The Include syntax can also be in string. Include 语法也可以是字符串。 Like this:像这样:

           db.Courses
            .Include("Module.Chapter")
            .Include("Lab")
            .Single(x => x.Id == id);

But the samples in LinqPad explains this better.LinqPad中的示例更好地解释了这一点。

In Entity Framework Core ( EF.core ) you can use .ThenInclude for including next levels.在 Entity Framework Core ( EF.core ) 中,您可以使用.ThenInclude来包含下一个级别。

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
    .ToList();

More information: https://docs.microsoft.com/en-us/ef/core/querying/related-data更多信息: https ://docs.microsoft.com/en-us/ef/core/querying/related-data

Note: Say you need multiple ThenInclude() on blog.Posts , just repeat the Include(blog => blog.Posts) and do another ThenInclude(post => post.Other) .注意:假设您在blog.Posts上需要多个ThenInclude() ,只需重复Include(blog => blog.Posts)并执行另一个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();

Include is a part of fluent interface, so you can write multiple Include statements each following other Include是 fluent interface 的一部分,因此您可以编写多个Include语句,一个接一个

 db.Courses.Include(i => i.Modules.Select(s => s.Chapters))
           .Include(i => i.Lab)
           .Single(x => x.Id == id); 

你也可以试试

db.Courses.Include("Modules.Chapters").Single(c => c.Id == id);

One may write an extension method like this:可以编写这样的扩展方法:

    /// <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;
    }

And use it like this even in a generic implementation:即使在通用实现中也可以这样使用它:

string[] includedNavigationProperties = new string[] { "NavProp1.SubNavProp", "NavProp2" };

var query = context.Set<T>()
.Include(includedNavigationProperties);

this is from my project这是我的项目

 var saleHeadBranch = await _context.SaleHeadBranch
 .Include(d => d.SaleDetailBranch)
 .ThenInclude(d => d.Item)
 .Where(d => d.BranchId == loginTkn.branchId)
 .FirstOrDefaultAsync(d => d.Id == id);

Here is my working example.这是我的工作示例。 AccountInfoes is parent for User, User is parent for Currency and for Country. AccountInfoes 是 User 的父级,User 是 Currency 和 Country 的父级。

var accountinfo =  _context.AccountInfoes.Include(a => a.User)
                         .Include(a=>a.User.Currency)
                       .Include(a => a.User.Country)
            .FirstOrDefaultAsync(ai => ai.UserId == userId);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM