EF Core 筛选包含 Select

EF Core Filtered Include with Select

对不起我的英语。

我 运行 在同时使用 Filtered Include 和 Select 时遇到了 EF Core 5.0.9 的错误,我不知道是错误还是功能。 :)

return await _dbContext.User
    .Where(u => !u.TOROLT)
    .Where(u => ids.Contains(u.Id))
    .Include(u => u.EventUsers.Where(eu => !eu.TOROLT && eu.EventId == eventId))
    .Select(u => new UserDropDownDtoWithInviteData
    {
        Id = u.Id,
        FirstName = u.FirstName,
        LastName = u.LastName,
        EventUserId = u.EventUsers.First().Id,
        IsCelebrated = u.EventUsers.First().IsCelebrated,
        IsEventAdmin = u.EventUsers.First().IsEventAdmin,
        IsInviteAccepted = u.EventUsers.First().IsInviteAccepted,
        IsInvited = u.EventUsers.First().IsInvited,
    })
    .ToListAsync();

此时第一个元素是 select 不是来自过滤包含,只是来自普通包含。 SQL 来自 Profiler 的脚本:

SELECT
[u].[Id],
[u].[FirstName],
[u].[LastName],
(
    SELECT TOP(1) [e].[Id]
    FROM [dbo].[EventUser] AS [e]
    WHERE [u].[Id] = [e].[UserId]) AS [EventUserId],
(
    SELECT TOP(1) [e0].[IsCelebrated]
    FROM [dbo].[EventUser] AS [e0]
    WHERE [u].[Id] = [e0].[UserId]) AS [IsCelebrated],
(
    SELECT TOP(1) [e1].[IsEventAdmin]
    FROM [dbo].[EventUser] AS [e1]
    WHERE [u].[Id] = [e1].[UserId]) AS [IsEventAdmin],
(
    SELECT TOP(1) [e2].[IsInviteAccepted]
    FROM [dbo].[EventUser] AS [e2]
    WHERE [u].[Id] = [e2].[UserId]) AS [IsInviteAccepted],
(
    SELECT TOP(1) [e3].[IsInvited]
    FROM [dbo].[EventUser] AS [e3]
    WHERE [u].[Id] = [e3].[UserId]) AS [IsInvited]
FROM [dbo].[User] AS [u]
WHERE ([u].[TOROLT] <> CAST(1 AS bit))
    AND [u].[Id] IN (2, 1, 3, 4, 5)

但是如果单独过滤包含和 select,那么它工作正常,但是这个 select 完整记录而不是他来自数据库的部分:

var a = await _dbContext.User
    .Where(u => !u.TOROLT)
    .Where(u => ids.Contains(u.Id))
    .Include(u => u.EventUsers.Where(eu => !eu.TOROLT && eu.EventId == eventId))
.ToListAsync();
return a.Select(u => new UserDropDownDtoWithInviteData
    {
        Id = u.Id,
        FirstName = u.FirstName,
        LastName = u.LastName,
        EventUserId = u.EventUsers.First().Id,
        IsCelebrated = u.EventUsers.First().IsCelebrated,
        IsEventAdmin = u.EventUsers.First().IsEventAdmin,
        IsInviteAccepted = u.EventUsers.First().IsInviteAccepted,
        IsInvited = u.EventUsers.First().IsInvited,
    })
    .ToList();

知道这是为什么吗,我该如何解决?

谢谢

如果您有自定义投影 Select

Include 将被完全忽略,因此您的过滤器也将被忽略。这不是错误,Include 仅当您从查询中获取整个实体时才有效。

无论如何考虑重写您的查询:

var query = 
    from u in _dbContext.User
    where !u.TOROLT && ids.Contains(u.Id)
    from eu in u.EventUsers.Where(eu => !eu.TOROLT && eu.EventId == eventId)
        .Take(1)
        .DefaultIfEmpty()
    select new UserDropDownDtoWithInviteData
    {
        Id = u.Id,
        FirstName = u.FirstName,
        LastName = u.LastName,
        EventUserId = eu.Id,
        IsCelebrated = eu.IsCelebrated,
        IsEventAdmin = eu.IsEventAdmin,
        IsInviteAccepted = eu.IsInviteAccepted,
        IsInvited = eu.IsInvited,
    };

var result = await query.ToListAsync();