【问题标题】:How to apply Contains( ) on a string array using LINQ to SQL c#如何使用 LINQ to SQL c# 在字符串数组上应用 Contains()
【发布时间】:2014-09-26 14:02:06
【问题描述】:

美好的一天!

string[] keywords = toolStripTextBoxSearch.Text.Split(' ');
IQueryable<employee> query = db.employees;
foreach (string keyword in keywords)
{
    query = query.Where(data => data.empName.Contains(keyword) 
                        || data.bank.bankCode.Contains(keyword) 
                        || data.bank.bankName.Contains(keyword) 
                        || data.department.deptName.Contains(keyword)
                        || data.department.deptCode.ToString().Contains(keyword) 
                        || data.designation.desigText.Contains(keyword) 
                        || data.empBankAccount.Contains(keyword) 
                        || data.empBasicSalary.Value.ToString().Contains(keyword) 
                        || data.empIncomeTax.ToString().Contains(keyword) 
                        || data.empName.Contains(keyword) 
                        || data.empNTN.Contains(keyword) 
                        || data.empTicketNumber.Contains(keyword) 
                        || data.grade.gradeText.Contains(keyword));
}

dataGridViewEmployee.DataSource = query;

现在,如果我在文本框中写 "a b",它不会显示任何结果,而仅写“a”或“b”时,只有 gridview 会显示多个结果。

【问题讨论】:

  • 您在每次迭代时都用新查询覆盖查询,最后一个关键字“b”是空字符吗?快速猜测你想要query.Where(d =&gt; keywords.Any(kw =&gt; data.empName.Contains(kw));
  • 问题是你应用的foreach关键字AND,所以结果会是(empName.Contains("a") OR empNTN.Contains("a") ...) AND (empName.Contains("b") OR empNTN.Contains("b") ...)(因为你是循环应用Where)。
  • 您能否更好地详细说明上下文以及您要完成的工作?例如,您引用了一个 gridview。您是在谈论 ASP.NET GridView 还是 winforms DataGridView。你能告诉我们一些与之相关的代码吗?
  • @Sayse 您的代码遇到异常 System.Data.Linq.dll 中发生“System.NotSupportedException”类型的未处理异常附加信息:本地序列不能在查询运算符的 LINQ to SQL 实现中使用除了包含运算符。
  • @AlexanderRyanBaggett 我正在开发 winforms 并拥有 datagridview

标签: c# sql linq foreach iqueryable


【解决方案1】:
string[] keywords = toolStripTextBoxSearch.Text.Split(' ');
IQueryable<employee> query = db.employees;

query = query.Where(data => keywords.Contains(data.empName) ||  
keywords.Contains(data.bank.bankCode) || 
keywords.Contains(data.bank.bankName) ||  
keywords.Contains(data.department.deptName) ||  
keywords.Contains(data.department.deptCode.ToString()) ||  
keywords.Contains(data.designation.desigText) ||  
keywords.Contains(data.empBankAccount) ||  
keywords.Contains(data.empBasicSalary.Value.ToString()) ||  
keywords.Contains(data.empIncomeTax.ToString()) ||  
keywords.Contains(data.empName) ||  
keywords.Contains(data.empNTN) ||  
keywords.Contains(data.empTicketNumber) ||  
keywords.Contains(data.grade.gradeText));

【讨论】:

    【解决方案2】:

    在路上是使用DynamicLinq

    using System.Linq.Dynamic;
    // ....
    
    var predicateBuilder = new StringBuilder();
    
    for (var i = 0; i < keywords.Length; i++)
    {
        predicateBuilder.AppendFormat("empName.Contains(@{0}) 
                                        OR data.bank.bankCode.Contains(@{0})
                                        OR data.bank.bankName.Contains(@{0})
                                        OR ... and so on", i);
    
        if (i < keywords.Length - 1)
        {
            predicateBuilder.Append(" OR ");
        }
    }
    
    query = query.Where(predicateBuilder.ToString(), 
                        keywords.Cast<object>().ToArray());
    
    var result = (IEnumerable<YourClass>)query.ToList();
    

    缺点

    1. 不是强类型。
    2. Prop 名称可能会出错,
    3. 重构不友好 - 您必须记住道具名称已更改并在字符串中手动执行..例如

    所以使用它,当没有人会给你更好的解决方案时。更多关于this blog

    【讨论】:

      【解决方案3】:

      "ab" 没有显示任何结果的原因是因为生成的SQL Query 可能不是你想要的样子。

      当只有一个关键字时,例如 "a""b",@ 987654323@ 就像:

      SELECT empName, bankCode, bankName, ...
      FROM Employees
      WHERE (empName LIKE '%a%') OR (bankCode LIKE '%a%') OR (bankName LIKE '%a%') ...
      

      但是当有多个关键字时,例如"a b",那么生成的SQL query会是这样的:

      SELECT empName, bankCode, bankName, ...
      FROM Employees
      WHERE ((empName LIKE '%a%') OR (bankCode LIKE '%a%') OR (bankName LIKE '%a%') ...) 
            AND ((empName LIKE '%b%') OR (bankCode LIKE '%b%') OR (bankName LIKE '%b%') ...) ...
      

      注意那里的AND 运算符,你想要的可能是一个ALL OR 条件...

      使用PredicateBuilder 是一种轻松实现您想要的方法。 您使用PredicateBuilder 的更新示例将是这样的:

      string[] keywords = toolStripTextBoxSearch.Text.Split(' ');
      IQueryable<employee> query = db.employees;
      Expression<Func<employee, bool>> predicate = PredicateBuilder.False<employee>();
      
      foreach (string keyword in keywords)
      {
        predicate = predicate.Or(data => data.empName.Contains(keyword) || data.bank.bankCode.Contains(keyword) || data.bank.bankName.Contains(keyword) || data.department.deptName.Contains(keyword) || data.department.deptCode.ToString().Contains(keyword) || data.designation.desigText.Contains(keyword) || data.empBankAccount.Contains(keyword) || data.empBasicSalary.Value.ToString().Contains(keyword) || data.empIncomeTax.ToString().Contains(keyword) || data.empName.Contains(keyword) || data.empNTN.Contains(keyword) || data.empTicketNumber.Contains(keyword) || data.grade.gradeText.Contains(keyword));
      }
      
      dataGridViewEmployee.DataSource = query.Where(predicate);
      

      【讨论】:

      • 非常感谢@IronGeek
      猜你喜欢
      • 2011-01-23
      • 2012-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-10
      • 1970-01-01
      • 2021-03-19
      • 1970-01-01
      相关资源
      最近更新 更多