【问题标题】:LINQ: Search/Filter data from multiple tableLINQ:从多个表中搜索/过滤数据
【发布时间】:2020-05-28 13:02:02
【问题描述】:

我有三张桌子,

表:1

 UserId  UserName     ...   
  1      Jhon        ...
  2      Ashley      ...
  3      Alexa       ... 
  4      Krish       ...

表:2

BrandId UserId  BrandName        
 1       1       BMW
 2       1       Citroen
 3       2       Audi
 4       4       Peugeot

表:3

CountryId UserId  CountryName        
 1          3       Austria

现在我想要的是,如果用户按 Brands = ["BMW", "Audi"] & countries= ["India","Romania"] 搜索项目,那么它应该显示如下用户结果:

 UserId  UserName     ...   
  1      Jhon        ...
  2      Ashley      ...

或仅按国家搜索项目= ["India","Austria"] 那么结果应该是:

 UserId  UserName     ...   
   3      Alexa       ...

我尝试过遵循 C#-LINQ,但我总是获取所有用户数据。它不是根据给定的品牌或国家输入进行过滤的。因此,如果品牌或国家/地区与数据库数据匹配,它应该提供数据。即使我从 LINQ 部分中删除“into”,它也没有正确给出。我哪里做错了?

 var users = new List<Users>();
 users = _DbContext.Users.Where(x => x.Roles == model.Role).ToList();
 users = (from p in users
                         join b in _DbContext.UserBrands.Where(x => model.arBrands.Contains(x.BrandName)).ToList() on p.UserSequence equals b.UserId into bg
                         join c in _DbContext.UserCountries.Where(x => model.arCountries.Contains(x.CountryName)).ToList() on p.UserSequence equals c.UserId into cg
                         select p).ToList();

还有我的示例有效负载,

{
 "arBrands": ["Citroen","Peugeot"],
 "arCountries":["India","Romania"],
 "Role":"All Roles"
}

实体:

public class UserBrands
{
    [Key] public virtual int UserBrandsId { get; set; }
    public virtual int UserId { get; set; }
    public virtual int BrandId { get; set; }
    public virtual string BrandName { get; set; }
}

public class UserCountries
{
    [Key] public virtual int UserCountriesId { get; set; }
    public virtual int UserId { get; set; }
    public virtual int CountryId { get; set; }
    public virtual string CountryName { get; set; }
}

public class UsersModel
{
    public string[] arCountries { get; set; }
    public string[] arBrands { get; set; }
    [Required]
    public string Role { get; set; }
    public List<LeafLet> features { get; set; }
}

public class Users : BaseEntity
{
    [Key]
    public virtual int UserSequence { get; set; }
    public virtual string UserName { get; set; }
    public virtual string Countries { get; set; }
    public virtual string Brands { get; set; }
    public virtual string Email { get; set; }
    public virtual string Latitude { get; set; }
    public virtual string Longitude { get; set; }
    public virtual string ProjectRole { get; set; }
    public virtual string Roles { get; set; }
}

【问题讨论】:

  • 你能添加你的实体吗?
  • 实际上,机密细节在那里,所以只是没有包括所有细节。对不起。如果我包含,那么任何人都可以轻松识别实际品牌的客户和名称等。
  • 我的意思是UsersUserBrandsUserCountries 类。您可以排除所有不重要的字段。
  • public class UserBrands { [Key] public virtual int UserBrandsId { get;放; } 公共虚拟 int UserId { 获取;放; } 公共虚拟 int BrandId { 获取;放; } 公共虚拟字符串 BrandName { 获取;放; } } public class UserCountries { [Key] public virtual int UserCountriesId { get;放; } 公共虚拟 int UserId { 获取;放; } 公共虚拟 int CountryId { 获取;放; } 公共虚拟字符串 CountryName { 获取;放; } }
  • 请将它们添加到问题中)

标签: c# linq lambda entity-framework-core


【解决方案1】:

您需要稍微清理一下模型,并添加导航属性以让 EF 为您执行连接。

    public class Users
    {
        [Key]
        public int Id { get; set; }
        public string UserName { get; set; }
        public string Email { get; set; }
        public string Role { get; set; }

        //Only use the virtual keyword for navigating properties to other entities.
        public virtual IEnumerable<UserBrand> UserBrands {get; set;}
        public virtual IEnumerable<UserCountry> UserCountries {get; set;}
    }

    public class UserBrand
    {
        [Key] 
        public int Id { get; set; }
        public int UserId { get; set; }
        public int BrandId { get; set; }

        [ForeignKey("UserId")] // lets Entity Framework know how to map the navigation.
        public virtual User User { get; set; }

        [ForeignKey("BrandId")]
        public virtual Brand Brand { get; set; }
    }


    public class Brand
    {   
        [Key]
        public int Id { get; set; }  
        public string BrandName { get; set; }
    }


    public class UserCountry
    {
        [Key] 
        public int Id { get; set; }
        public int UserId { get; set; }
        public int CountryId { get; set; }

        [ForeignKey("UserId")]
        public virtual User User { get; set; }

        [ForeignKey("CountryId")]
        public virtual Country Country { get; set; }
    }

    public class Country
    {
        [Key] 
        public int Id { get; set; }
        public string CountryName { get; set; }
    }

您的 LINQ 查询将如下所示:

 var users = _DbContext.Users
                 .Where(u => u.Role == model.Role)
                 .Select(u => new { 
                      UserName = u.UserName,
                      Email = u.Email,
                      Role = u.Role,
                      BrandNames = u.UserBrands.Select(ub => ub.Brand.BrandName),
                      Countries = u.UserCountries.Select(uc => uc.CountryName)
                  }).ToList();

您可以使用导航属性向 Where 子句添加更多过滤器:

 var users = _DbContext.Users
                 .Where(u => u.Role == model.Role 
                       && u.UserBrands.Any(ub => 
                              ub.Brand.BrandName == "Brand X") //Filter for brand name.
                       && u.UserCountries.Any(uc => 
                              uc.Country.CountryName == "United States") //Filter for brand name.

                 .Select(u => new { 
                      UserName = u.UserName,
                      Email = u.Email,
                      Role = u.Role,
                      BrandNames = u.BrandNames,
                      Countries = u.Countries
                           })
                 .ToList();

【讨论】:

  • 我会试试这个,让你知道。谢谢你的帮助斯蒂芬!。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-28
  • 2021-03-07
  • 1970-01-01
  • 2013-05-24
  • 1970-01-01
  • 2020-03-20
相关资源
最近更新 更多