繁体   English   中英

计数 Linq 查询与多连接 EF

[英]Count in Linq query with multiple join EF

嗨 Helpies 我是 EF 和 linq 查询的新手

        var chatEntryDetails = await
            (
                from chatEntry in dbChatEntry
                where chatEntry.ChatId == chat.Id
                join groupMembers in dbGroupMember on chatEntry.GroupMemberId equals groupMembers.Id
                join user in dbUser on groupMembers.UserId equals user.Id
                join countChatEntryUserStatus in dbChatEntryUserStatus.Where(e => e.DateReadByUser != null).Count() on chatEntry.Id equals countChatEntryUserStatus.ChatEntryId
                join chatEntryUserStatus in dbChatEntryUserStatus.Where(e => e.GroupMemberId == groupMemberId) on chatEntry.Id equals chatEntryUserStatus.ChatEntryId into ce
                from chatEntryUserStatus in ce.DefaultIfEmpty()
                orderby chatEntry.CreateDateTime descending
                select new ChatEntryDetails
                {
                    UserId = user.Id, GreetingName = user.GreetingName, GroupMemberId = chatEntry.GroupMemberId,
                    CreateDateTime = chatEntry.CreateDateTime, Details = chatEntry.Details, ChatType = ToApi(chatEntry.ChatType),
                    DateReadByUser = chatEntryUserStatus.DateReadByUser, ChatEntryId = chatEntry.Id, ReadByCount = countChatEntryUserStatus
                }
            )
            .PerPage(page, perPage)
            .ToListAsync();

执行此操作时出现以下错误

Could not find an implementation of the query pattern for source type 'IQueryable<<anonymous type: <anonymous type: <anonymous type: <anonymous type: ChatEntryDb chatEntry, GroupMemberDb groupMembers> <>h__TransparentIdentifier0, UserDb user> <>h__TransparentIdentifier1, IEnumerable<ChatEntryUserStatusDb> ce> <>h__TransparentIdentifier2, ChatEntryUserStatusDb chatEntryUserStatus>>'.  'Join' not found. [UserServerApiLib]

没有这条线一切正常

join countChatEntryUserStatus in dbChatEntryUserStatus.Where(e => e.DateReadByUser != null).Count() on chatEntry.Id equals countChatEntryUserStatus.ChatEntryId

在这里我想要计数 chatEntryUserStatus 其中 DateReadByUser 不是 null 此行应该从 chatEntryUserStatus 表中获取计数,但条件很少有一个表 chatEntry 并且它们与 chatEntry.id = chatEntryUserStatus.ChatEntryId 相关,并且对于每个 chatEntry 它都有多条记录chatEntryUserStatus 所以我希望每个 chatEntry 的 chatEntryUserStatus 计数

如果不算数,那么如果我可以获得每个 chatEntry 的所有 chatEntryUserStatus 记录

提前致谢

基于

是的,导航属性在那里

并查看此 Linq 声明:

var chatEntryDetails = await
(
    from chatEntry in dbChatEntry
    where chatEntry.ChatId == chat.Id
    join groupMembers in dbGroupMember on chatEntry.GroupMemberId equals groupMembers.Id
    join user in dbUser on groupMembers.UserId equals user.Id
    join countChatEntryUserStatus in dbChatEntryUserStatus.Where(e => e.DateReadByUser != null).Count() on chatEntry.Id equals countChatEntryUserStatus.ChatEntryId
    join chatEntryUserStatus in dbChatEntryUserStatus.Where(e => e.GroupMemberId == groupMemberId) on chatEntry.Id equals chatEntryUserStatus.ChatEntryId into ce
    from chatEntryUserStatus in ce.DefaultIfEmpty()
    orderby chatEntry.CreateDateTime descending
    select new ChatEntryDetails
    {
        UserId = user.Id, 
        GreetingName = user.GreetingName, 
        GroupMemberId = chatEntry.GroupMemberId,
        CreateDateTime = chatEntry.CreateDateTime, 
        Details = chatEntry.Details, 
        ChatType = ToApi(chatEntry.ChatType),
        DateReadByUser = chatEntryUserStatus.DateReadByUser, 
        ChatEntryId = chatEntry.Id, 
        ReadByCount = countChatEntryUserStatus
    }
}
.PerPage(page, perPage)
.ToListAsync();

然后看起来您可以利用这些导航属性,例如:

var chatEntryDetails = await context.ChatEntries
    .Where(c => c.Chat.Id == chatId)
    .Select(c => new ChatEntryDetails
    {
        UserId = c.GroupMember.User.Id,
        GreetingName = c.GroupMember.User.GreetingName,
        GroupMemberId = c.GroupMember.Id,
        CreateDateTime = c.CreateDateTime,
        Details = c.Details,
        ChatType = c.ChatType, 
        DateReadByUser = c.ChatEntryUserStatuses
            .Max(s => s.CreateDateTime),
        ChatEntryId = c.Id,
        ReadByCount = c.ChatEntryUserStatuses.Count()
   }).Skip(pageCount * pageSize)
   .Take(pageSize)
   .ToListAsync();

这比通过连接筛选要简单得多。 您可能需要查看的两个偏差是 ChatType 上的ToApi()修饰符和似乎提供分页的PerPage()方法。 Select中的任何内容最终都需要通过 EF 归结为 SQL,因此即使没有最初的“计数”连接问题, ToApi()也很有可能会触发异常。 (早期的 EF Core 版本在检测到类似的东西时会拉取查询客户端。它可以让您免于异常,但通常会破坏查询的性能和 memory 占用空间)如果我不得不猜测我会说这是翻译将字符串或数值转换为适合此数据使用者的另一个值。 如果您想将诸如 1、2、3、4 之类的值转换为“A”、“B”、“C”、“D”,那么这可能有点棘手。 在 LINQ 表达式中,您可以使用 (? :) 即:

ChatType = c.ChatType == 1 ? "A" : c.ChatType == 2 ? "B" : c.ChatType == 3 ? "C" : c.ChatType == 4 ? "D" : "?"

这是相当混乱的。 相反,我通常建议在 ViewModel (ChatEntryDetails) 中按原样填充 ChatType,并添加一个已翻译的 ApiChatType 属性,该属性跨 ChatType 执行switch()语句以返回适当的翻译。

对于分页,使用标准的 Linq 分页方法SkipTake以确保这些也被转换为 SQL 查询。 我们可以使用Max从用户状态中获取最新的 CreateDateTime,尽管OrderByDescending + FirstOrDefault + Select也可以在这里工作。 readByCount 是通过询问相关状态的Count来提供的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM