如何通过循环访问字符串搜索参数的集合来编写 Linq 'or'查询



我有一个基于字符串的搜索参数列表:

即 {"部分名称1", "部分名称2", "部分名称3",

..., "部分名称(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))
        }

有什么办法可以做到这一点吗?

你应该以相反的方式比较它,就像:

var query = personQuery.Where(p => searchPhrases.Any(r=> p.Name.Contains(r));

感谢@GertArnold我通过他关于谓词生成器的评论找到了自己的方式。

快速介绍"由谓词生成器编写查询的 c# linq"

我找到了一个 LINQKit 的"linq": http://www.albahari.com/nutshell/linqkit.aspx

现在我知道SO不喜欢链接作为答案,但我不确定我是否会抄袭(一些建议会很有用)

谓词生成器非常酷,可以轻松地以编程方式编写查询(复制自 albahari 网站):

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 到实体查询表达式中。

这让我想到了皮特·蒙哥马利(Pete Montgomery)的一篇名为《通用谓词生成器》的博客。

事实证明,正如Pete所解释的那样,由于依赖于InvocationExpressions,Albahari版本不能很好地与实体框架配合使用。如果您使用的是 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);
    }

虽然我已经给出了这个作为答案,而且确实如此。我没有这样标记它,因为这不是我要给出的答案,如果皮特或约瑟夫(阿尔巴哈里)遇到这个问题并希望创建一个答案,我会这样标记它。

最新更新