在联接表上使用EF Core的ThenInclude()

38

我正在将我的.NET Framework (EF6) 代码转换为ASP.NET Core (EF Core),在这个过程中遇到了问题。以下是一些示例代码:

在EF6中,我使用Include()和Select()进行急加载:

return _context.Post
.Include(p => p.PostAuthor.Select(pa => pa.Author).Select(a => a.Interests))

PostAuthor是一个连接表,还有一个连接表"AuthorInterest",在EF6中我不需要涉及它(选择直接到a.Interests)。

无论如何,我可以看到在EF7中这已经重新组织了,这意味着我现在应该使用ThenInclude()进行嵌套查询。 但是...

return _context.Post
  .Include(p => p.PostAuthor)
    .ThenInclude(pa => pa.Select(pa2 => pa2.Author))
...etc
上述代码因为Select()语句而失败。在https://docs.efproject.net/en/latest/querying/related-data.html上的文档似乎暗示我不需要它,可以直接访问Author,但是最后一个lambda表达式中显示了ICollection,所以显然我需要Select()。在查询中,我还需要通过多个连接表,但为简单起见,我们只关注第一个连接表。

如何使其工作?

1个回答

60
但是在最后的 lambda 表达式中,我得到了一个 ICollection,所以我显然需要使用 Select()。 不,你不需要。EF Core 的 Include/ThenInclude 完全取代了 EF6 中用于导航属性的 Select/SelectMany。它们都有单独的重载用于集合和引用类型导航属性。如果您使用具有集合参数的重载,则 ThenInclude 操作于集合元素的类型上,因此最终您总是会得到一个实体类型。 在您的情况下,pa 应该解析为您的连接表元素类型,所以 Author 应该直接可访问。 例如,EF6 的 include 链:
.Include(p => p.PostAuthor.Select(pa => pa.Author).Select(a => a.Interests))

翻译为EF Core:

.Include(p => p.PostAuthor).ThenInclude(pa => pa.Author).ThenInclude(a => a.Interests)

30
哇,谢谢。非常奇怪——Visual Studio没有给我pa.Author提供智能感知(而是建议一些Linq方法),并且只要我试着写它,就会用红色下划线标出所有东西。 在你的发帖之后,我忽略了VS,在编译后一切都像魔法一样运行了。 - nikovn
1
很奇怪。我正在使用VS2015 Update 3,当我编写像db.Parents.Include(p => p.Children).ThenInclude(c => c.Child).ThenInclude(c => c.Parents)这样的代码时,每个lambda表达式都能得到正确的智能感知支持。 - Ivan Stoev
8
我使用的是Visual Studio 2017预览版2,我遇到了相同的智能感应错误。忽略它并成功构建即可 :) - muhihsan
1
我在使用Visual Studio 2017 Pro时也遇到了IntelliSense问题,由于这里的评论中还有其他人遇到了此问题,因此我为EF团队在GitHub上开了一个问题:https://github.com/aspnet/EntityFramework/issues/9374 - Matt Sanders
2
缺乏智能感知是Roslyn的问题。请参见https://github.com/dotnet/roslyn/issues/8237 如果您使用第三方工具,如R#,则可以扩展智能感知以提供正确的结果。 - Smit
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接