LINQ to Entities - Select 用户的所有好友以及他们之间的聊天
LINQ to Entities - Select all the User's friends and the Chat between them
如何Select当前登录用户的所有好友以及用户与好友之间的私人聊天(聊天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();
友谊table
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; }
}
用户table
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; }
}
聊天用户table
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; }
}
谢谢
这个查询:
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();
...加载用户朋友与朋友相应的聊天,其中包括不与当前用户的聊天。
有了用于聊天和友谊的域结构,尝试 link 以有意义的方式建立它们看起来相当棘手。使用简单的两遍方法很可能:
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();
聊天与两个或更多用户相关,与 restricted/linked 友谊无关。
Joe 可以与 Sam、Jane 和 John 成为朋友,并进行以下聊天:
聊天 1:乔 <-> 山姆
聊天 2:乔 <-> 简
聊天 3:乔 <-> 简 <-> 山姆
聊天 4:乔 <-> 弗兰克
聊天 5:乔 <-> 弗兰克 <-> 萨姆
我们想要聊天 1、2、3 和 5 returned。没有与 John 的聊天,我们不关心与 Frank 的聊天,但确实关心与 Frank 和 Sam 的聊天,因为 Sam 是朋友。目标是确定 Joe 正在与他的一个或多个朋友进行哪些聊天。对于每场比赛,我们 return 聊天以及当前也在该聊天中的任何朋友。
两次传递方法的警告是,它假设朋友列表将保持相当小,不会大到超过为获得匹配聊天而生成的 IN()
列表。
如何Select当前登录用户的所有好友以及用户与好友之间的私人聊天(聊天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();
友谊table
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; }
}
用户table
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; }
}
聊天用户table
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; }
}
谢谢
这个查询:
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();
...加载用户朋友与朋友相应的聊天,其中包括不与当前用户的聊天。
有了用于聊天和友谊的域结构,尝试 link 以有意义的方式建立它们看起来相当棘手。使用简单的两遍方法很可能:
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();
聊天与两个或更多用户相关,与 restricted/linked 友谊无关。
Joe 可以与 Sam、Jane 和 John 成为朋友,并进行以下聊天:
聊天 1:乔 <-> 山姆
聊天 2:乔 <-> 简
聊天 3:乔 <-> 简 <-> 山姆
聊天 4:乔 <-> 弗兰克
聊天 5:乔 <-> 弗兰克 <-> 萨姆
我们想要聊天 1、2、3 和 5 returned。没有与 John 的聊天,我们不关心与 Frank 的聊天,但确实关心与 Frank 和 Sam 的聊天,因为 Sam 是朋友。目标是确定 Joe 正在与他的一个或多个朋友进行哪些聊天。对于每场比赛,我们 return 聊天以及当前也在该聊天中的任何朋友。
两次传递方法的警告是,它假设朋友列表将保持相当小,不会大到超过为获得匹配聊天而生成的 IN()
列表。