Linq-to-SQL:组合(OR'ing)多个“包含”过滤器?

时间:2010-12-21 16:12:16

标签: c# .net linq-to-sql

我在找出实现这一目标的最佳方法时遇到了一些麻烦,我将不胜感激。

基本上,我正在设置一个过滤器,允许用户查看与用户名的任意“过滤器”相关联的审核项目的历史记录。

数据源是一个SQL Server数据库,所以我正在使用IQueryable“source”(来自db上下文对象的直接表引用,或者可能是由其他查询产生的IQueryable),应用WHERE过滤器,然后返回结果的IQueryable对象....但我对如何使用这种方法执行OR有点难过。

我已经考虑过表达式的路径,因为我知道如何对它们进行OR,但我还是无法通过“包含”类型评估来弄清楚如何做到这一点,所以我目前正在使用UNION,但我担心这可能会对性能产生负面影响,我想知道如果在arbirary顺序中添加其他过滤器(除了此处显示的用户名过滤),它是否可能无法完全满足我的要求。

以下是我的示例代码:

public override IQueryable<X> ApplyFilter<X>(IQueryable<X> source)
{
    // Take allowed values...
    List<string> searchStrings = new List<string>();

    // <SNIP> (This just populates my list of search strings)

    IQueryable<X> oReturn = null;

    // Step through each iteration, and perform a 'LIKE %value%' query
    string[] searchArray = searchStrings.ToArray();
    for (int i = 0; i < searchArray.Length; i++)
    {
        string value = searchArray[i];
        if (i == 0)
            // For first step, perform direct WHERE
            oReturn = source.Where(x => x.Username.Contains(value));
        else
            // For additional steps, perform UNION on WHERE
            oReturn = oReturn.Union(source.Where(x => x.Username.Contains(value)));
    }
    return oReturn ?? source;
}

这感觉就像做错事的方式,但它确实有效,所以我的问题首先是,有更好的方法吗?另外,有没有办法用表达式做'包含'或'喜欢'?

(编辑纠正我的代码:为了发布它回滚到工作状态,我显然没有回滚得足够远:))

=============================================

ETA:根据给出的解决方案,这是我的新代码(如果有人对此感兴趣):

public override IQueryable<X> ApplyFilter<X>(IQueryable<X> source)
{
    List<string> searchStrings = new List<string>(AllowedValues);

    // <SNIP> build collection of search values 

    string[] searchArray = searchStrings.ToArray();

    Expression<Func<X, bool>> expression = PredicateBuilder.False<X>();

    for (int i = 0; i < searchArray.Length; i++)
    {
        string value = searchArray[i];
        expression = expression.Or(x => x.Username.Contains(value));
    }
    return source.Where(expression);
}

(我注意到一个警告:在PredicateBuilder的示例之后,搜索字符串的空集合将返回false(false || value1 || ...),而在我的原始版本中,我假设一个空列表应该只是对于未经过滤的来源。当我想到它时,新版本似乎对我的需求更有意义,所以我采用了它)

=============================================

1 个答案:

答案 0 :(得分:7)

您可以使用LINQkit中的PredicateBuilder动态构建查询。