LINQ to Entities - 选择用户的所有朋友以及他们之间的聊天

Posted

技术标签:

【中文标题】LINQ to Entities - 选择用户的所有朋友以及他们之间的聊天【英文标题】:LINQ to Entities - Select all the User's friends and the Chat between them 【发布时间】:2022-01-01 13:48:03 【问题描述】:

如何选择当前登录用户的所有好友以及用户与好友之间的私聊(聊天 ID)?我能够获取用户的朋友,但也无法获取他们之间的聊天。

            // Select all the User's friends and the chat (Id) between them
            var friends = await _context.Friendships // Get the Friendships
                .Include(x => x.Friend).ThenInclude(x => x.ChatUsers).ThenInclude(x => x.Chat)
                .Where(x => x.Status == StatusCode.Accepted && x.ApplicationUserId == userId)
                .Select(x => x.Friend)
                .ToListAsync();

友谊表

    public class Friendship
    
        // The primary keys/foreign keys of the associated tables
        public string ApplicationUserId  get; set; 
        public string ApplicationFriendUserId  get; set; 

        // Reference to the user that has the friend
        public User ApplicationUser  get; set; 

        // Reference to the friend
        public User Friend  get; set; 

        // The status of the friendship
        public StatusCode Status  get; set; 
    

用户表

    public class User : IdentityUser
    
        // Reference to all user's chats
        public ICollection<ChatUser> ChatUsers  get; set; 

        // Reference to all the user's friendships
        public ICollection<Friendship> UsersFriendships  get; set; 

        // Reference to all the friend's friendships (their point of view)
        public ICollection<Friendship> FriendsFriendships  get; set; 
    

ChatUser 表

    public class ChatUser
    
        // The primary key/foreign keys of the associated tables
        public int ChatId  get; set; 
        public string UserId  get; set; 

        // The role that the User can be
        public UserRole Role  get; set; 

        // Reference to the chat
        public Chat Chat  get; set; 

        // Reference to the user
        public User User  get; set; 
    

聊天

    
    public class Chat
    
        // The primary key
        public int Id  get; set; 

        // The chat's name
        public string Name  get; set; 

        // The chat type, e.g room, private
        public ChatType Type  get; set; 

        // Reference to all the Chat's Users
        public ICollection<ChatUser> ChatUsers  get; set; 
    

谢谢

【问题讨论】:

【参考方案1】:

这个查询:

var friends = await _context.Friendships // Get the Friendships
    .Include(x => x.Friend).ThenInclude(x => x.ChatUsers).ThenInclude(x => x.Chat)
    .Where(x => x.Status == StatusCode.Accepted && x.ApplicationUserId == userId)
    .Select(x => x.Friend)
    .ToListAsync();

... 将用户好友与好友对应的聊天加载,其中包括与当前用户无关的聊天。

使用聊天和友谊的域结构,尝试以有意义的方式将它们链接起来看起来相当棘手。使用简单的两遍方法很可能是可能的:

var friendIds = _context.Users
    .Where(x => s.UserId == userId)
    .SelectMany(x => x.UsersFriendships.Where(f => f.Status == StatusCode.Accepted).Select(f => f.ApplicationFriendUserId))
    .ToList(); // Get all accepted Friend IDs.


 var chats = _context.Chats
     .Where(x => x.ChatUsers.Any(cu => cu.UserId) && x => x.ChatUsers.Any(cu => friendIds.Contains(cu.UserId)
     .Select(x => new 
     
         Chat = x,
         Friends = x.ChatUsers.Where(cu => friendIds.Contains(cu.UserId)).Select(cu => cu.User).ToList()
      ).ToList();

聊天与两个或多个用户相关,并且不受友谊限制/链接。

Joe 可以与 Sam、Jane 和 John 成为朋友,并且可以进行以下聊天:

聊天 1:乔 山姆

聊天 2:乔 简

聊天 3:乔 简 山姆

聊天 4:乔 弗兰克

聊天 5:乔 弗兰克 山姆

我们希望返回聊天 1、2、3 和 5。没有与 John 的聊天,我们不关心与 Frank 的聊天,但关心与 Frank 和 Sam 的聊天,因为 Sam 是朋友。目标是确定 Joe 正在与他的一个或多个朋友参与哪些聊天。对于每场比赛,我们都会返回聊天以及当前也在该聊天中的所有好友。

两遍方法的注意事项是,它假定朋友列表将保持相当小,不会大到超过为获取匹配聊天而生成的 IN() 列表。

【讨论】:

以上是关于LINQ to Entities - 选择用户的所有朋友以及他们之间的聊天的主要内容,如果未能解决你的问题,请参考以下文章

LINQ to Entities 选择新建

使用 Linq to Entities (EF6) 动态选择列名

在 LINQ to Entities 中重用选择表达式

使用Linq to Entities在一个请求中选择计数和计数

在 Linq-to-Entities 查询中格式化日期会导致异常

查询 LINQ to Entities 中联系字段的属性