LINQ to Entities查询当前登录用户的好友及对应私聊Chat ID
解决方法
你当前代码的问题是:Select(x => x.Friend) 仅返回了好友实体,好友关联的 ChatUsers 包含了该好友所有的会话,无法直接筛选出仅属于你和该好友的私聊。
方案1:直接投影查询(适合数据量较小的场景)
首先定义一个数据传输对象(DTO)用来封装返回结果,避免暴露多余的实体字段:
public class FriendWithChatDto { // 可按需扩展好友的其他字段,比如昵称、头像等 public string FriendId { get; set; } public string FriendUserName { get; set; } // 你和该好友的私聊ID public int? PrivateChatId { get; set; } }
查询逻辑如下,EF Core 会自动加载投影所需的关联数据,无需手动写 Include:
var result = await _context.Friendships .Where(x => x.Status == StatusCode.Accepted && x.ApplicationUserId == userId) .Select(x => new FriendWithChatDto { FriendId = x.Friend.Id, FriendUserName = x.Friend.UserName, // 筛选同时包含当前登录用户、且是私聊类型的会话 PrivateChatId = x.Friend.ChatUsers .Where(cu => cu.Chat.Type == ChatType.Private && cu.Chat.ChatUsers.Any(u => u.UserId == userId)) .Select(cu => cu.Chat.Id) .FirstOrDefault() }) .ToListAsync();
方案2:分两次查询(适合好友量较大的场景,性能更优)
如果好友数量较多,嵌套子查询生成的SQL性能较差,可以先把当前用户的所有私聊会话查出来做映射,再和好友列表匹配:
// 第一步:查询当前用户所有私聊,生成「好友ID-私聊ID」的字典 var privateChatMap = await _context.Chats .Where(c => c.Type == ChatType.Private && c.ChatUsers.Any(u => u.UserId == userId)) .Select(c => new { ChatId = c.Id, // 私聊仅有两个用户,排除自己剩下的就是好友ID FriendId = c.ChatUsers.First(u => u.UserId != userId).UserId }) .ToDictionaryAsync(x => x.FriendId, x => x.ChatId); // 第二步:查询已通过的好友列表 var friends = await _context.Friendships .Where(x => x.Status == StatusCode.Accepted && x.ApplicationUserId == userId) .Select(x => x.Friend) .ToListAsync(); // 第三步:匹配每个好友对应的私聊ID,可自行组装返回格式 foreach (var friend in friends) { if (privateChatMap.TryGetValue(friend.Id, out var chatId)) { // 按需处理ChatId赋值即可 } }
内容的提问来源于stack exchange,提问作者JAmes
相关产品推荐
相关产品推荐

