EF Core,投影子集合急切加载

9
在 EF core 中,我正在尝试投影一个带有子集合的结果集。
 ctx.As.Select(a => new
    {
        AId = a.Id,
        BNames = a.Bs.Select(x=>x.Name) //SubCollection
    })

然而,当执行这个操作时,BNames集合是惰性的,所以当它被枚举时,它会为每一行触发一个单独的查询,例如在B的集合中有2个项目。
[a].[Id] AS [AId] FROM [As] AS [a]

p_executesql N'SELECT [x].[Name]
FROM [Bs] AS [x]
WHERE @_outer_Id = [x].[AId]',N'@_outer_Id int',@_outer_Id=1

p_executesql N'SELECT [x].[Name]
FROM [Bs] AS [x]
WHERE @_outer_Id = [x].[AId]',N'@_outer_Id int',@_outer_Id=2

在EF6中,同样的查询结果如下(正如我所期望的):
SELECT 
[Extent1].[Id] AS [Id], 
[Project1].[C1] AS [C1], 
[Project1].[Name] AS [Name]
FROM  [dbo].[A] AS [Extent1]
LEFT OUTER JOIN  (SELECT 
    [Extent2].[Name] AS [Name], 
    [Extent2].[A_Id] AS [A_Id], 
    1 AS [C1]
    FROM [dbo].[B] AS [Extent2] ) AS [Project1] ON [Extent1].[Id] = [Project1].[A_Id]
ORDER BY [Extent1].[Id] ASC, [Project1].[C1] ASC

我该如何让EF预先加载子集合BNames
注意:这不同于使用.Include包含子实体的问题,因为这是一个自定义投影,而不是导航属性。在此处使用.Include会导致错误。
完整代码库在此处:https://gist.github.com/lukemcgregor/692834629da09b21d5a35515e86c9002
1个回答

5
使用EF Core 2.1的相关子查询优化,可以实现这一点。
您需要升级到EF Core 2.1,并通过在子查询中添加“.ToList()”来进行优化的小修改:
foreach (var thing in ctx.As
    .Select(a => new
    {
        AId = a.Id,
        BNames = a.Bs.Select(x => x.Name).ToList()
    }))

请查看EF Core 2.1的新功能中的相关子查询优化


1
哈哈,具有讽刺意味的是,我使用投影的整个原因是因为我在2.1之前没有支持.Aggregate ;) - undefined
2.1版本应该在一两天内发布(不要引用我),在此之前请使用2.1.0早期访问下载 - Martin Ullrich
在 EF 的后续版本中不再相关。OP 的查询只翻译成了一个 SQL 查询。 - Gert Arnold

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