C# 使用LINQ搜索多个术语

C# 使用LINQ搜索多个术语,c#,linq-to-sql,C#,Linq To Sql,我希望能够对多个单词进行基本搜索。本质上,使用LINQ执行与SQL查询等效的操作 SELECT * FROM table WHERE column LIKE '%foo%' OR column LIKE '%bar%' 我在这里发现了一些类似的问题,它们大多提供相同的解决方案,将输入拆分,然后使用Any搜索所有单词。但是,在使用此解决方案时,我遇到了一个错误 除Contains运算符外,查询运算符的LINQ到SQL实现中不能使用局部序列 我理解错误消息意味着我不能使用任何-只有包含。但这对

我希望能够对多个单词进行基本搜索。本质上,使用LINQ执行与SQL查询等效的操作

SELECT * 
FROM table 
WHERE column LIKE '%foo%' OR column LIKE '%bar%'
我在这里发现了一些类似的问题,它们大多提供相同的解决方案,将输入拆分,然后使用
Any
搜索所有单词。但是,在使用此解决方案时,我遇到了一个错误

除Contains运算符外,查询运算符的LINQ到SQL实现中不能使用局部序列

我理解错误消息意味着我不能使用
任何
-只有
包含
。但这对我来说没有意义,因为这里的解决方案成功地使用了
Any

这是我的密码

var termString = "foo bar";
var searchTerms = termString.Split(' ');
var itemsList = (from items in myDataContext.myDatabaseTable
                 where searchTerms.Any(term => items.ColumnName.Contains(term))
                 select items).ToList();
使用它或您自己的简化实现,您可以创建扩展为一系列单独测试的谓词,如SQL中的谓词

我的完整库中有
whereny
wherell
WhereSplitContains
以及它们的谓词基。您需要一个
位置
s:

// searchTerms - IEnumerable<TSearch> where one must match for a row
// testFne(row,searchTerm) - test one of searchTerms against a row
// r => searchTerms.All(s => testFne(r,s))
public static Expression<Func<T, bool>> AnyIs<T, TSearch>(this IEnumerable<TSearch> searchTerms, Expression<Func<T, TSearch, bool>> testFne) {
    var pred = PredicateBuilder.New<T>();
    foreach (var s in searchTerms)
        pred = pred.Or(r => testFne.Invoke(r, s));

    return pred;
}

// searchTerms - IEnumerable<TSearch> where one must match for a row
// testFne(row,searchTerm) - test one of searchTerms against a row
// dbq.Where(r => searchTerms.Any(s => testFne(r,s)))
public static IQueryable<T> WhereAny<T,TSearch>(this IQueryable<T> dbq, IEnumerable<TSearch> searchTerms, Expression<Func<T, TSearch, bool>> testFne) =>
    dbq.AsExpandable().Where(searchTerms.AnyIs(testFne));
使用它或您自己的简化实现,您可以创建扩展为一系列单独测试的谓词,如SQL中的谓词

我的完整库中有
whereny
wherell
WhereSplitContains
以及它们的谓词基。您需要一个
位置
s:

// searchTerms - IEnumerable<TSearch> where one must match for a row
// testFne(row,searchTerm) - test one of searchTerms against a row
// r => searchTerms.All(s => testFne(r,s))
public static Expression<Func<T, bool>> AnyIs<T, TSearch>(this IEnumerable<TSearch> searchTerms, Expression<Func<T, TSearch, bool>> testFne) {
    var pred = PredicateBuilder.New<T>();
    foreach (var s in searchTerms)
        pred = pred.Or(r => testFne.Invoke(r, s));

    return pred;
}

// searchTerms - IEnumerable<TSearch> where one must match for a row
// testFne(row,searchTerm) - test one of searchTerms against a row
// dbq.Where(r => searchTerms.Any(s => testFne(r,s)))
public static IQueryable<T> WhereAny<T,TSearch>(this IQueryable<T> dbq, IEnumerable<TSearch> searchTerms, Expression<Func<T, TSearch, bool>> testFne) =>
    dbq.AsExpandable().Where(searchTerms.AnyIs(testFne));

使用
Any
的“解决方案”从不针对数据库,只针对列表。原始SQL非常慢,因为它必须扫描整个表以查找匹配项<像“%foo%”这样的代码>无法从索引中获益。您不应该尝试在LINQ中重新创建这个缓慢的查询,而应该添加一个并使用FTS谓词,如CONTAINS,FREETEXT从2.1开始在EF Core中可用。@PanagiotisKanavos full test search Index不幸的是,实际上并不是很有用,因为它们是基于术语/单词的,并且不会找到部分单词匹配,也不应被视为中缀
搜索的好替代方法。也许my可以帮助您。@NetMage这正是它们真正有用的地方,尤其是在这种情况下。是的,他们会找到部分匹配,因为他们使用词干,实际上可以匹配单词的多种形式。LIKE不是一个替代方案,即使在一个小数据集上,性能也会非常糟糕。OP正在寻找文字。没有一种方法能够解决使用
Any
索引“解决方案”的不足永远不会针对数据库,只针对列表。原始SQL非常慢,因为它必须扫描整个表以查找匹配项<像“%foo%”这样的代码>无法从索引中获益。您不应该尝试在LINQ中重新创建这个缓慢的查询,而应该添加一个并使用FTS谓词,如CONTAINS,FREETEXT从2.1开始在EF Core中可用。@PanagiotisKanavos full test search Index不幸的是,实际上并不是很有用,因为它们是基于术语/单词的,并且不会找到部分单词匹配,也不应被视为中缀
搜索的好替代方法。也许my可以帮助您。@NetMage这正是它们真正有用的地方,尤其是在这种情况下。是的,他们会找到部分匹配,因为他们使用词干,实际上可以匹配单词的多种形式。LIKE不是一个替代方案,即使在一个小数据集上,性能也会非常糟糕。OP正在寻找文字。没有一种方法能够解决索引不足的问题