【问题标题】:C# Chaining multiple LINQ contains to search for userC# 链接多个 LINQ 包含以搜索用户
【发布时间】:2023-02-15 21:10:56
【问题描述】:

我正在尝试通过搜索用户列表来将用户添加到团队中。

我正在使用 linq 搜索数据以根据多个字段找到匹配项

data = data.Where(x =>
                    x.Name.ToLower().Contains(filter) ||
                    x.Surname.ToLower().Contains(filter) ||
                    x.PhoneNumber.ToLower().Contains(filter) ||
                    x.Email.ToLower().Contains(filter) ||
                    x.AthleteTeams.All(x => x.Team.Name.Contains(filter)) ||
                    x.AthleteTeams.All(x => x.Athlete.AthleteGender.Equals(filter)) ||
                    x.AthleteTeams.All(x => x.Athlete.AthleteRace.Equals(filter))
                );

但是,结果仅适用于名字、姓氏和电子邮件。

当搜索所有字段时,它会返回看似随机的用户,而不是满足指定过滤器的用户

【问题讨论】:

  • 它返回看似随机的用户,而不是满足指定过滤器的用户--> 能否提供一个具体的示例场景并提供datafilter、预期输出和实际输出的值?
  • 你确定你需要All而不是Any吗?请注意,空集合的 All 在 LINQ-to-Objects 中始终为真。
  • 数据将是具有名称的用户列表。电子邮件地址电话号码等。过滤器将是您在搜索栏中输入的内容。例如一个人或键入“Jo”应该调出“John”,但调出“Amy”之类的东西
  • @MylesLouw 示例数据不够具体。由于您有很多 OR 条件,因此可以进行很多潜在的匹配。此外,您在某些地方使用.ToLower(),而其他地方则不用。这是故意的吗? filter.ToLower()ed了吗?

标签: c# asp.net-mvc linq asp.net-core


【解决方案1】:

例如,我猜你不想找到所有 AthleteTeams 具有相同团队名称的用户。这意味着您有多个名称相似的团队。

例如,我猜你实际上想找到所有 AthleteTeams 至少包含一个名称匹配的团队的用户。所以使用 Any 并且只使用 AthleteTeams 的一个查询而不是三个:

 ....
 x.AthleteTeams.Any(x => x.Team.Name.Contains(filter)
                     ||  x.Athlete.AthleteGender.Equals(filter)
                     ||  x.Athlete.AthleteRace.Equals(filter))

但是,我发现此过滤器逻辑很奇怪且容易出错。您的搜索性能会很慢并且会出现许多错误匹配,因为总会有一些匹配项,而用户却不知道为什么。最好通过姓名和电话号码等最常见的属性提供搜索,在用户至少输入 3 个字符并提供特定的团队搜索之前不要开始搜索。

【讨论】:

    【解决方案2】:

    但是,结果仅适用于名字、姓氏和电子邮件。

    我觉得PhoneNumber应该也可以。

    当搜索所有字段时,它会返回看似随机的用户,而不是满足指定过滤器的用户

    Enumerable.All 对于空集合将始终为真:

    Console.WriteLine(new int[]{}.All(i => false)); // prints True
    

    尝试使用类似的东西:

    data = data.Where(x =>
        ... || (x.AthleteTeams.Any() && (
        x.AthleteTeams.All(x => x.Team.Name.Contains(filter)) ||
        x.AthleteTeams.All(x => x.Athlete.AthleteGender.Equals(filter)) ||
        x.AthleteTeams.All(x => x.Athlete.AthleteRace.Equals(filter))))
    );
    

    也可能你实际上首先需要 Any 而不是 All

    data = data.Where(x =>
        ... 
        || x.AthleteTeams.Any(x => x.Team.Name.Contains(filter) 
                 || x.Athlete.AthleteGender.Equals(filter)
                 ||  x.Athlete.AthleteRace.Equals(filter))
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-02
      • 2014-03-13
      • 2021-05-01
      相关资源
      最近更新 更多