EntityFramework:包含导航属性与包含选择之间的差异?

ful*_*ris 0 c# entity-framework-core

这更多的是一个语法问题,而不是一个实际的错误或错误,因为我终于得到了我想要的工作。但我想了解并改进我当前的解决方案。

模式

假设我有一个Users表,与 table 具有一对多关系Posts,还有一个进一步的一对一关系表Authors- 每个表一个Post

我想编写一个自定义存储库函数来获取 all Users、 with all Posts、 with every Authorper Post

尝试#1(不起作用)

我想我可以做这样的事情:

public IQueryable<User> GetUsersWithPostsAndAuthors()
{
    var query = GetAll();

    // include all details on user object
    return query
        .Include(user => user.Posts.Select(x => x.Author));
}
Run Code Online (Sandbox Code Playgroud)

它似乎不包括该Author实体。实际上,我收到以下错误:

Lambda expression used inside Include is not valid.
Run Code Online (Sandbox Code Playgroud)

尝试#2(也不起作用)

然后我想也许这些Posts需要首先出现在查询中,所以我尝试了以下方法:

Lambda expression used inside Include is not valid.
Run Code Online (Sandbox Code Playgroud)

不幸的是,我遇到了同样的错误:

Lambda expression used inside Include is not valid.
Run Code Online (Sandbox Code Playgroud)

尝试#3(有效!)

Include但是,如果我使用您可以提供 a的版本string navigationPropertyPath(实际上我不喜欢,因为它只是一个硬编码字符串),如下所示:

public IQueryable<User> GetUsersWithPostsAndAuthors()
{
    var query = GetAll();

    // include all details on user object
    return query
        .Include(user => user.Posts)
        .Include(user => user.Posts.Select(x => x.Author)
}
Run Code Online (Sandbox Code Playgroud)

查询按预期工作!

这里发生了什么?我认为Select投影会起到与 相同的作用Include。(Stackoverflow 上似乎有一些答案表明了这一点。)

更重要的是,有没有一种方法可以完成我想要的任务,而无需Posts.AuthorInclude通话中进行硬编码?我想在这里进行静态类型检查。

Ger*_*old 5

这里发生了什么?

无意冒犯,但无非是不太明白其Include用途。它仅用于包含导航属性,不适用于投影。

语法非常清晰:

后一个示例等效于.Include("Posts.Author"),但由于编译时检查,首选 lambda 语法。在旧的 EF6 版本中没有ThenInclude,包含更多级别的语法如您所写:.Include(user => user.Posts.Select(x => x.Author))

投影是SelectLINQ 查询中的,而不是Include语句中的。例如:

return query.Select(u => new { u.Id, u.Name });
Run Code Online (Sandbox Code Playgroud)

Includes相互推算和排斥。在投影中,没有任何内容可以包含导航属性。像这样的查询:

return query
    .Include(u => u.Posts)
    .Select(u => new 
    {
        u.Id, 
        u.Name,
        Posts = u.Posts.Select(p => p.Title)
    });
Run Code Online (Sandbox Code Playgroud)

会完全忽略Include。在生成的 SQL 中没有任何痕迹:只会Post.Title查询,而不是Post像 an 那样查询所有字段Include