如何使用LINQ在字符串数组上应用Contains()

本文关键字:应用 Contains 数组 何使用 LINQ 字符串 | 更新日期: 2023-09-27 18:16:19

大家好!

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显示多个结果。

如何使用LINQ在字符串数组上应用Contains()

为什么写"a b"没有显示任何结果是因为生成的SQL Query可能不像您想要的那样。

当只有一个关键字时,例如"a""b"SQL query将是:

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);
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));

方法之一是使用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. 重构不友好-你必须记住道具名称已经更改,并在字符串中手动执行。例如

所以,当没有人给你更好的解决方案时,使用它。