我有一个基于字符串的搜索参数列表:
即。 {“partialName1”,“partialName2”,“partialName3”,...,“partialName(N)”} 我不会知道N的大小是什么。
我想通过迭代这个字符串集合来编写一个Linq(Linq-to-Entities)“OR”查询,并编写一个与下面的查询等效的查询:
var specialFolk = people.Where(p => p.Name.Contains("partialName1") || p.Name.Contains("partialName2") || p.Name.Contains("partialName3") || ... || p.Name.Contains("partialName(N)"));
以下代码演示了我想要做的事情。但它不会起作用,它只是我想用于以可组合方式构建OR查询的概念的说明
List<string> searchPhrases = searchPhraseGiveToUsFromAbove;
IQueryable<Person> personQuery;
foreach(string searchPhrase in searchPhrases)
{
personQuery = personQuery.Where(p=>p.Name.Contains(searchPhrase))
}
有没有办法实现这个目标?
答案 0 :(得分:6)
您应该以相反的方式比较它:
var query = personQuery.Where(p => searchPhrases.Any(r=> p.Name.Contains(r));
答案 1 :(得分:1)
感谢@GertArnold我找到了关于谓词构建器的评论。
关于“c#linq由谓词构建器组成查询”的快速提示
我找到了LINQKit的“linq”:http://www.albahari.com/nutshell/linqkit.aspx
现在我知道SO不喜欢链接作为答案,但我不确定我是否会抄袭(有些建议会有用)
谓词构建器非常酷,可以轻松地以编程方式编写查询(从albahari website复制):
IQueryable<Product> SearchProducts (params string[] keywords)
{
var predicate = PredicateBuilder.False<Product>();
foreach (string keyword in keywords)
{
string temp = keyword;
predicate = predicate.Or (p => p.Description.Contains (temp));
}
return dataContext.Products.Where (predicate);
}
然后有一条评论'如果使用实体框架查询,请将最后一行更改为:'
return objectContext.Products.AsExpandable().Where (predicate);
但是我想把这些谓词链接成更复杂的东西,我被错误所困扰:
参数“f”未绑定在指定的LINQ to Entities查询表达式中。
这导致我的Pete Montgomery博客标题为universal predicate builder
事实证明,Pete解释说,由于依赖于InvocationExpressions,Albahari版本与Entity框架不能很好地兼容。如果您使用EF,Pete关于此的博客非常值得一读。
我再次不想复制并粘贴他的解决方案(这是他的,他提供免费),但我会展示我能够构建的查询,最终解决了我的问题:
private IQueryable<Show> BuildQueryForLibrarySearchTerms(IEnumerable<LibraryShowSearchTerm> searchTerms)
{
IQueryable<Show> query = _repository.Get();
IEnumerable<LibraryShowSearchTerm> includeTerms = searchTerms.Where(st=>st.Exclude.Equals(false));
IEnumerable<LibraryShowSearchTerm> excludeTerms = searchTerms.Where(st=>st.Exclude.Equals(true));
var predicate = LinqPredicateBuilder.False<Show>();
var includePredicate = LinqPredicateBuilder.False<Show>();
foreach (LibraryShowSearchTerm searchTerm in includeTerms)
{
string temp = searchTerm.SearchTerm;
includePredicate = includePredicate.Or(show => show.ShowTitle.Contains(temp));
}
var excludePredicate = LinqPredicateBuilder.True<Show>();
foreach (LibraryShowSearchTerm searchTerm in excludeTerms)
{
string temp = searchTerm.SearchTerm;
excludePredicate = excludePredicate.And(show => !show.ShowTitle.Contains(temp));
}
predicate = includePredicate.And(excludePredicate);
return query.Where(predicate);
}
虽然我已经给出了这个答案,但确实如此。我不是这样说的,因为这不是我给出的答案,如果Pete或Joseph(Albahari)遇到这个并希望创建一个答案,我会将其标记为。