在Linq中部分搜索空格分隔的值
本文关键字:分隔 空格 搜索 Linq 中部 | 更新日期: 2023-09-27 18:08:18
我有一个字段说公司名称,并希望部分搜索用户输入的数据,可能是空格分隔。假设用户输入"ABC India PVT Ltd"查询必须搜索包含一个或多个输入单词的所有记录。就像在SQL中,它是
Select *
from Company
where CompanyName like '%ABC%' or
CompanyName like '%India%' or
CompanyName like '%PVT%' or
CompanyName like '%Ltd%'
我正在尝试做这样的事情
string search = "ABC India PVT Ltd"
String[] searchArray = search.Split(' ');
IEnumerable<Account> accountInfo = acctInfo.Get(Filter: a
=>searchArray.AsQueryable().Contains(a.CompanyName));
但是这给了我与我想要达到的完全相反的结果。有什么方法可以做到这一点吗?
基本思想是通配符搜索,companyname字段的任何searchArray值。
a.CompanyName。
这就成功了。使用Any()筛选包含以下关键字之一的记录:
string searchTerm = "ABC India PVT Ltd";
string[] keywords = searchTerm.Split(' ');
List<Records> records = new List<Records>();
records.Add(new Records() { CompanyName = "Foo name" });
records.Add(new Records() { CompanyName = "ABC name" });
records.Add(new Records() { CompanyName = "Foo India" });
records.Add(new Records() { CompanyName = "PVT name" });
records.Add(new Records() { CompanyName = "Foo name" });
records.Add(new Records() { CompanyName = "Foobar" });
records.Add(new Records() { CompanyName = "Stackoverflow" });
var results = records.Where(x => keywords.Any(keyword => x.CompanyName
.Contains(keyword))).ToList();
虚拟类:
public class Records
{
public Records() { }
public string CompanyName { get; set; }
}
将给您一个List<Record>
的记录,其CompanyName
包含任何关键字。如
- "ABC名称"
- 印度"Foo"
- "PVT名称"
DGibbs提出的Any
解决方案适用于少量元素(这可能是您的情况,所以我赞成),但EF无法从此构造构建有效的查询。下面是只有4个元素的查询:
SELECT
-- some fields
FROM [dbo].[Company] AS [Extent1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM (SELECT
[UnionAll2].[C1] AS [C1]
FROM (SELECT
[UnionAll1].[C1] AS [C1]
FROM (SELECT
N'a' AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
UNION ALL
SELECT
N'b' AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable2]) AS [UnionAll1]
UNION ALL
SELECT
N'c' AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable3]) AS [UnionAll2]
UNION ALL
SELECT
N'd' AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable4]) AS [UnionAll3]
WHERE ( CAST(CHARINDEX([UnionAll3].[C1], [Extent1].[Name]) AS int)) > 0
)
这是不可伸缩的。超过一定数量的元素(只有几十个),查询将抛出一个SQL异常,表示超过了最大嵌套级别。
为了防止这种情况,您应该使用OR
子句构建查询。这就是PredicateBuilder可以提供帮助的地方:
var predicate = PredicateBuilder.False<Company>();
foreach (var keyword in searchArray)
{
predicate = predicate.Or(c => c.Name.Contains(keyword));
}
var query = Companies.Where(predicate.Expand());
顺便说一下,有一个替代LINQKit的PredicateBuilder的源代码,它做同样的事情,但没有Expand
。