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

Posted

技术标签:

【中文标题】EF LINQ 包括多个和嵌套的实体【英文标题】:EF LINQ include multiple and nested entities 【发布时间】:2013-03-23 18:35:25 【问题描述】:

好的,我有具有以下层次结构的三级实体:课程 -> 模块 -> 章节

这是原始的 EF LINQ 语句:

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

现在,我想包含另一个名为 Lab 的实体,它与课程相关联。

如何包含 Lab 实体?

我尝试了以下方法,但没有成功:

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

关于包含第二个实体的任何想法?

我们将不胜感激任何建议或信息。谢谢!

【问题讨论】:

添加另一个 .Include 应该可以工作,除非您的意思是附加的包含是 Course 的孙子。 See this 或 better option is this ***.com/q/3356541的相关/可能重复 【参考方案1】:

您是否尝试过添加另一个Include

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

您的解决方案失败了,因为 Include 不采用布尔运算符

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

更新 要了解更多信息,请下载 LinqPad 并查看示例。 我认为这是熟悉 Linq 和 Lambda 的最快方法。

首先 - SelectInclude 之间的区别在于,您可以通过 Select 决定 要返回的内容(也称为投影)。 Include 是一个 Eager Loading 函数,它告诉 Entity Framework 您希望它包含来自其他表的数据。

Include 语法也可以是字符串。像这样:

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

但LinqPad 中的示例更好地解释了这一点。

【讨论】:

欣赏!我在哪里可以了解更多信息?我对 Include 和 Select 之间的区别特别感兴趣 只有这个对我有用:.Include("Module.Chapter")。知道为什么会这样吗? @JoSmo 您需要导入命名空间System.Data.Enity 才能访问扩展方法。更多信息here using System.Data.Entity; 做到了。谢谢! 因提及出色的 linqpad 以及使用 System.Data.Entity 的提示而被投票赞成,感谢 Jens【参考方案2】:

在 Entity Framework Core (EF.core) 中,您可以使用 .ThenInclude 来包含下一个级别。

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

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

注意: 假设您需要在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();

【讨论】:

在 EF.core 中我似乎无法执行 .Include(i => i.Modules.Select(s => s.Chapters)),特别是 .Include 中的 .Select。任何人都可以确认或交谈吗? @ttugates 你打算用这个选择做什么?我认为您想要做的正是您在 EF 核心中使用 ThenInclude 所做的事情。也许提出一个很好的例子,以便我们回答它。 @Nick N - Entity Framework Linq Query: How to Where on Multiple Nav Properties and Select from 3rd Nav Property。因为我选择的不是我要匹配的,所以不需要包含,所以问题是切线的。我的问题可能过于“狭隘”,但感谢您的帮助。 啊。实际上, .ThenInclude() 确实有效。智能感知显示相关表格只需要很长时间。【参考方案3】:

Include是fluent interface的一部分,所以你可以写多个Include语句一个接一个

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

【讨论】:

欣赏!你能指出我在哪里可以学到更多吗?谢谢! 如果 Modules 有多个要加入的表,你知道语法是什么吗?说它链接到章节和其他内容? 是 .Net 的 fluent 部分还是需要安装的库?【参考方案4】:

你也可以试试

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

【讨论】:

谢谢 - 字符串中的点符号非常有用 这很有用,但是,不使用它的一个原因是以后易于重构:如果您在某个时候重命名“章节”实体,另一个示例将自动重命名。另一个是错误会更快被发现:在编译时,而不是运行时。 @MGOwen 我同意你的评论。但是,也可以使用:db.Courses.Include($"nameof(Modules).nameof(Chapters)").Single(c => c.Id == id);【参考方案5】:

可以这样写一个扩展方法:

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

即使在通用实现中也可以这样使用它:

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

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

【讨论】:

我正在尝试您的答案,但由于自身存在无限循环,它会抛出 ***exceptions。 @VictoriaS.,你可以重命名扩展方法,这样就不会干扰真正的Include【参考方案6】:

这是我的项目

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

【讨论】:

感谢您抽出宝贵时间提供答案。!你能:- 1)编辑你的答案,以便详细回答。 2)解释你想用这个答案实现什么以及你想说什么。?有关更多信息,请参阅如何在帮助中心写出好的答案(如何提问:***.com/help/how-to-answer) var saleHeadBranch = await _context.SaleHeadBranch .Include(d => d.SaleDetailBranch) .Include("SaleDetailBranch.Item") .Where(d => d.BranchId == loginTkn.branchId) 。 FirstOrDefaultAsync(d => d.Id == id);

以上是关于EF LINQ 包括多个和嵌套的实体的主要内容,如果未能解决你的问题,请参考以下文章

EF7 如何处理嵌套实体的更新操作

EF Core 嵌套 Linq 选择导致 N + 1 个 SQL 查询

具有自身 parentId 的实体框架核心嵌套对象

帮助我使用实体框架从 SQL 转换为 linq 嵌套 lambda 表达式

Linq:获取具有多个嵌套组的内部对象的小计

EF Core - 为啥“无限”嵌套急切加载?