【问题标题】:Linq Many to many in Entity Framework coreLinq 实体框架核心中的多对多
【发布时间】:2019-01-29 19:05:56
【问题描述】:

我有建立多对多关系的类。

public class Chat 
{
    [Key]
    public Guid Id { get; set; }
    public ICollection<ApplicationUserChat> UserChats { get; set; }
}

public class ApplicationUserChat
{
    [Required]
    public string UserId { get; set; }
    public ApplicationUser User { get; set; }

    public Guid ChatId { get; set; }
    public Chat Chat { get; set; }
}

public class ApplicationUser : IdentityUser
{        
    public ICollection<ApplicationUserChat> UserChats { get; set; }       
}

例如,我有一个user1user2

  1. 我需要为user1 选择聊天,其中聊天包含user2
  2. 我需要为 user1 选择聊天,其中聊天包含 user2 并且不包含其他用户(例如一个聊天仅包含 2 个参与者)

    如何通过一个对 DB 的请求在 EF Core 中执行此操作?

【问题讨论】:

  • 不应该UserIdApplicationUser 上吗?
  • @devNull,是的,applicationUser 包含 UserId
  • 第一个:首先,将UserIduser1user2 放入字符串列表 - userIdList,然后是dbContext.Chat.Where(x =&gt; x.UserChats.Any(y =&gt; userIdList.Contains(y.UserId)))。我建议使用用户 ID 的原因是为了避免在不同数据库上下文中获取查询结果时产生混淆。
  • 您需要在一个请求中同时获取 12 还是每个案例一个请求?

标签: c# entity-framework .net-core entity-framework-core asp.net-core-2.1


【解决方案1】:

如果可以接受对数据库执行 2 次查询以获取两种情况下的数据,则可以使用以下查询

//chats that contain user1 and user2
var chats1 = context
    .Chats
    .Where(c => c.UserChats.Any(u => u.UserId == userId1))
    .Where(c => c.UserChats.Any(u => u.UserId == userId2))
    .ToList();

//chats that contain user1 and user2 and they are only users in chat
var chats2 = context
    .Chats
    .Where(c => c.UserChats.Any(u => u.UserId == userId1))
    .Where(c => c.UserChats.Any(u => u.UserId == userId2))
    .Where(c => c.UserChats.Count() == 2)
    .ToList();

如果您想在 1 个请求中检索所有数据,您可以声明一个包含所需聊天信息的新类

public class ChatDto
{
    public Guid Id { get; set; }

    public int UserCount { get; set; }
}

并执行以下请求

var chats = context
    .Chats
    .Where(c => c.UserChats.Any(u => u.UserId == userId1))
    .Where(c => c.UserChats.Any(u => u.UserId == userId2))
    .Select(c => new ChatDto
    {
        Id = c.Id,
        UserCount = c.UserChats.Count()
    })
    .ToList();

因此,您将拥有包含 user1user2 的聊天以及聊天中的用户总数。

【讨论】:

    【解决方案2】:
     var chats = user1.UserChats.Select(uc => uc.ChatId).Distinct();
     var result1 = context.ApplicationUserChat
           .Where(a => a.UserId == user2.Id && chats.Contains(a.ChatId))
           .Select(a => a.Chat)
           .ToList();
     var result2 = results1.Except(context.ApplicationUserChat
           .Where(a => a.UserId != user2.Id 
                       && a.UserId != user2.Id 
                       && chats.Contains(a.ChatId))
           .Select(a => a.Chat)
           .Distinct())
           .ToList();
    

    //正在加载...使用/如果您已经拥有用户列表的简短版本:

     var result1 = user1.UserChat.Intersect(user2.UserChats);
    

    【讨论】:

    • 感谢您的回答,它可以帮助我,但可能我们有一个变体通过一个请求执行此操作,我认为执行 3 对 DB 的请求对性能不利
    猜你喜欢
    • 2020-01-26
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 2019-05-06
    • 1970-01-01
    相关资源
    最近更新 更多