具有多个连接条件的 Fluent LINQ 查询,其中一个是简单的等于,另一个是 id 之间的小于比较

Fluent LINQ query with multiple join conditions, one of which being a simple equals and another a less than comparison between ids

我有一个 SQL 查询,其中包括一个左连接和一个分组依据 - 到目前为止一切顺利 - 我的问题来自于其中一个连接条件不是直接 "equals to" 并且我'我迷失了 LINQ 的去向。

我知道多个连接条件通常涉及创建几个匿名对象并比较它们,但是当我将 "equal to" 和 "a greater" 添加到组合中时,我不知道这是怎么回事适用。

如果我发明了 LINQ,这就是我希望查询的样子,但我知道我的连接条件中的 "and" 无效;

        var query =
            from csp in db.ChatSessionPersons
            join cm in db.ChatMessages on 
                csp.ChatSessionId equals cm.ChatSessionId 
                and cm.Id > csp.LastReadChatMessageId  
                        // (i know these should be the other way round, 
                        // but for readability I present them like this!)
            into j1
            from j2 in j1.DefaultIfEmpty()
            group j2 by csp.ChatSessionId into grouped
            select new {
                  ChatSessionId = grouped.Key, 
                  UnreadCount = grouped.Count(t => t.Id != null)};

有什么想法吗?

您可以将不相等条件转换为组加入结果的 lambda Where

var query = from csp in db.ChatSessionPersons
            join cm in db.ChatMessages on csp.ChatSessionId equals cm.ChatSessionId into cmj
            select new {
                ChatSessionId = csp.ChatSessionId, 
                UnreadCount = cmj.Where(cm => cm.Id > csp.LastReadChatMessageId).Count()
            };

注意:我稍微修改了查询以删除 group by 如果您使用的是已经对匹配结果进行分组的组连接则不需要它,并删除左连接 DefaultIfEmpty 在处理像 Count 这样的组连接时也不需要它,除非你想 return 一个 UnreadCount 为 1 当没有匹配时,在这种情况下你应该将 DefaultIfEmpty() 放在 Count().

之前

当然,您可以在子查询中使用查询理解:

var query = from csp in db.ChatSessionPersons
            join cm in db.ChatMessages on csp.ChatSessionId equals cm.ChatSessionId into cmj
            select new {
                ChatSessionId = csp.ChatSessionId, 
                UnreadCount = (from cm in cmj where cm.Id > csp.LastReadChatMessageId select cm).Count()
            };