如何撰写Linq'或者#39;通过迭代字符串搜索参数的集合来查询

时间:2015-03-06 20:08:35

标签: c# linq linq-to-entities

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

即。 {“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))
        }

有没有办法实现这个目标?

2 个答案:

答案 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)遇到这个并希望创建一个答案,我会将其标记为。