EF LINQ包含多个嵌套实体


155

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

这是原始的EF LINQ语句:

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

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

如何包括实验室实体?

我尝试了以下操作,但没有成功:

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

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

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


1
.Include除非您认为附加的include是Course的孙代,否则添加另一个应该可以。看到这个更好的选择是
von v。13年

Answers:


234

您是否尝试过添加另一个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是与一个选择,你决定什么要返回(又名投影)。Include是一个急切的加载函数,它告诉Entity Framework您希望它包含来自其他表的数据。

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

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

但是样品在 LinqPad中对此进行了更好的解释。


赞赏!我在哪里可以了解更多?我对“包含”和“选择”之间的区别特别感兴趣
AnimaSola 2013年

3
仅此一项对我有用:.Include("Module.Chapter")。知道为什么会这样吗?
Jo Smo 2015年

5
@JoSmo,您需要导入名称空间System.Data.Enity以访问扩展方法。更多信息在这里
Jens Kloster

using System.Data.Entity;做到了。谢谢!
Jo Smo

1
赞扬了提及出色的linqpad,并提示使用System.Data.Entity,thx Jens
Mike Mike

38

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

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

详细信息:https : //docs.microsoft.com/zh-cn/ef/core/querying/related-data

注意: 假设您需要ThenInclude()启用多个blog.Posts,只需重复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

@ttugates您打算对此选择做什么?我认为您想要做的正是您ThenInclude在EF核心中所做的。也许用一个很好的例子来提问,以便我们回答。
Nick N.

@Nickñ - 实体框架LINQ查询:如何从3导航物业多重导航性能和选择在哪里。因为我选择的不是我要匹配的内容,所以包含不是必需的,因此问题是切线的。我的问题可能太“狭n”,但不胜感激。
ttugates

1
啊。实际上,.ThenInclude()确实起作用。只是花了很多时间才能让智能感知显示相关表。
克里斯J

23

Include是流畅接口的一部分,因此您可以Include互相写多个语句

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

谢谢!您能指出我在哪里可以学到更多吗?谢谢!
AnimaSola

1
您是否知道Modules有多个要联接的表的语法是什么?说它链接到章节和其他内容吗?
David Spence

流利的软件是.Net的一部分,还是需要安装的库?
Codea 2015年

19

您也可以尝试

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

4
谢谢-字符串中的点表示法非常有用
Evert

1
这可能很有用,但是不使用它的一个原因是以后易于重构:如果在某个时候重命名“ Chapters”实体,则另一个示例将自动重命名。另一个是错误会更早发现:在编译时,而不是运行时。
MGOwen

2

可以这样编写一种扩展方法:

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

我正在尝试您的答案,但由于自身无限循环,它引发了stackoverflowexceptions。
Victoria S.

1
@VictoriaS。,您可以重命名扩展方法,以免干扰真实的方法Include
Mohsen Afshin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.