【问题标题】:Filter with Left Join in Entity Framework在实体框架中使用左连接过滤
【发布时间】:2020-02-01 15:12:49
【问题描述】:

我在 ASP.NET Core API 项目中有 UserContactContactOfUser 实体。我想根据这些表的输入过滤用户。

我的实体类是这样的:

    public class User
    {
        public int Id { get; set; }

        [MaxLength(50)]
        public string Name { get; set; }

        [MaxLength(50)]
        public string Surname { get; set; }

        [MaxLength(60)]
        public string Username { get; set; }
}

public class Contact
{
    public int Id { get; set; }

    [MaxLength(50)]
    public string Value{ get; set; }
}

public class ContactOfUser
{
    public int Id { get; set; }

    public int UserId { get; set; }
    [ForeignKey(nameof(UserId))]
    public User User { get; set; }

    public int ContactId { get; set; }
}

我想根据这个FilterModel 对象过滤用户:

public class FilterModel
{
     public string Name { get; set; }
     public string Surname { get; set; }
     public string Username { get; set; }
     public List<int> ContactId { get; set; }
}

考虑到当数据被接受为空时不应用特殊过滤器数据,我如何使用 Linq 方法在实体框架中进行此过滤过程?

我做了类似的方法,但它不能正常工作:

List<User> GetFilteredUsers(FilterModel filter)
{
    var query1 = dbContext.Users
                          .Where(u => u.Name.Contains(filter.Name ?? string.Empty) &&
                                      u.Surname.Contains(filter.Surname ?? string.Empty) &&
                                      u.Username.Contains(filter.Username ?? string.Empty));

    var query2 = from u in query1
                 join cu in dbContext.ContactOfUsers on u.Id equals cu.UserId
                 into res
                 from item in res.DefaultIfEmpty()
                 where filter.Contacts.Contains(item.ContactId)
                 select new InitialUserModel
                         {
                             Id = u.Id,
                             Name = u.Name,
                             Surname = u.Surname,
                             Username = u.Username
                         };
}

【问题讨论】:

  • 到目前为止你尝试了什么?
  • 经常看到,您不使用导航属性。而这个FilterModel的作用是什么?你最好展示你自己的努力,无论多么尝试,以阐明其预期用途。

标签: sql entity-framework asp.net-core


【解决方案1】:

你可以这样实现

  • 使用GroupBy相应地得到userIdContactIds
var userContactIds = _dbContext.ContactOfUser.GroupBy(p => p.UserId).Select(g => new { UserId = g.UserId,  ContactIds = g.Select(p => p.ContactId).ToList() });
  • 得到结果:
var result = _dbContext.User.Select(p => new FilterModel 
{ 
   Name = p.Name, Surname = p.Surname, Username = p.Username, 
   ContactId = userContactIds.Where(c => p.Id == c.UserId).ToList() 
});

更新

List<User> GetFilteredUsers(FilterModel filter)
{
     return (from u in _dbContext.User
            join c in _dbContext.ContactOfUser on u.Id equals c.UserId
            join fContactId in filter.ContactId on c.ContactId equals fContactId 
            where u.Name == filter.Name && u.Surname == filter.Surname && u.Username == filter.Username 
            select u).ToList();
}

【讨论】:

  • @Phong,感谢您的回答。如果我不能清楚地解释我的问题,我很抱歉。实际上我想返回我的用户列表,而不是 FilterModel。 FilterModel 代表用户过滤请求。 *我通过指定预期的方法模型来编辑我的问题。
  • 嗯。我刚刚更新了我的答案。但是,按名称过滤不是一个好方法。如果我是你,我会改用UserId
  • 您应用了所有包含在 filterModel 但不包含在 contactIds 中的属性。
  • 是的,不需要包含contactIds
  • 是的,这正是我想要的。非常感谢
猜你喜欢
  • 2011-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 2013-05-15
  • 2020-10-06
  • 1970-01-01
相关资源
最近更新 更多