简体   繁体   English

Linq PredicateBuilder具有条件AND,OR和NOT过滤器

[英]Linq PredicateBuilder with conditional AND, OR and NOT filters

We have a project using LINQ to SQL, for which I need to rewrite a couple of search pages to allow the client to select whether they wish to perform an and or an or search. 我们有一个使用LINQ to SQL的项目,为此我需要重写几个搜索页面以允许客户端选择是否要执行 / 搜索。

I though about redoing the LINQ queries using PredicateBuilder and have got this working pretty well I think. 我虽然使用PredicateBuilder重做LINQ查询,但我认为这个工作得很好。 I effectively have a class containing my predicates, eg: 我实际上有一个包含我的谓词的类,例如:

internal static Expression<Func<Job, bool>> Description(string term)
{
    return p => p.Description.Contains(term);
}

To perform the search i'm doing this (some code omitted for brevity): 要执行搜索,我正在执行此操作(为简洁起见,省略了一些代码):

public Expression<Func<Job, bool>> ToLinqExpression()
{
    var predicates = new List<Expression<Func<Job, bool>>>();
    // build up predicates here

    if (SearchType == SearchType.And)
    {
        query = PredicateBuilder.True<Job>();
    }
    else
    {
        query = PredicateBuilder.False<Job>();
    }

    foreach (var predicate in predicates)
    {
        if (SearchType == SearchType.And)
        {
            query = query.And(predicate);
        }
        else
        {
            query = query.Or(predicate);
        }
    }
    return query;
}

While i'm reasonably happy with this, I have two concerns: 虽然我对此感到满意,但我有两个顾虑:

  1. The if/else blocks that evaluate a SearchType property feel like they could be a potential code smell. 评估SearchType属性的if / else块感觉它们可能是潜在的代码味道。
  2. The client is now insisting on being able to perform 'and not' / 'or not' searches. 客户现在坚持能够执行'而不是'/'或不执行'搜索。

To address point 2, I think I could do this by simply rewriting my expressions, eg: 为了解决第2点,我想我可以通过简单地重写我的表达式来做到这一点,例如:

internal static Expression<Func<Job, bool>> Description(string term, bool invert)
{
    if (invert)
    {
        return p => !p.Description.Contains(term);
    }
    else
    {
        return p => p.Description.Contains(term);
    }
}

However this feels like a bit of a kludge, which usually means there's a better solution out there. 然而,这感觉有点像一个kludge,这通常意味着那里有一个更好的解决方案。 Can anyone recommend how this could be improved? 任何人都可以推荐如何改善这一点? I'm aware of dynamic LINQ, but I don't really want to lose LINQ's strong typing. 我知道动态LINQ,但我真的不想失去LINQ的强类型。

If you are looking for less lines you can replace the if/else with ternary operator: 如果您正在寻找更少的线路,您可以使用三元运算符替换if / else:

query = SearchType == SearchType.And ? PredicateBuilder.True<Job>() : PredicateBuilder.False<Job>();

   foreach (var predicate in predicates)
   {
        query = SearchType == SearchType.And ? query.And(predicate) : query.Or(predicate);
   }

for the 'and not' / 'or not' part the ! 对于'and not' / 'or not'部分! operator should do the trick. 操作员应该做的伎俩。

PD: Did you test the foreach part is correctly setting the predicates?, as far as i remember you are building the expression that will be executed at later point in time, so you may have a literal reference just to the last set predicate in the final iteration, and that's why you must use a temp variable to save the value of each iteration. PD:你是否测试了foreach部分是否正确设置了谓词?,据我所知,你正在构建将在稍后的时间点执行的表达式,所以你可能只有一个文字参考,只有最后一个设置谓词在最后的迭代,这就是为什么你必须使用临时变量来保存每次迭代的值。

EDIT: If you want to negate a expression programmatic, that's a tricky one, you can try something like: 编辑:如果你想否定一个程序性的表达式,这是一个棘手的,你可以尝试类似的东西:

internal static Expression<Func<Job, bool>> Description(string term, bool invert)
        {
           return NegateExp<Func<Job, bool>>(p => p.Description.Contains(term), invert);
        }

And the NegateExp method will be something like: 而NegateExp方法将类似于:

public static Expression<TDelegate> NegateExp<TDelegate>(Expression<TDelegate> expression, bool inverse)
        {
            if (inverse)
            {
                return Expression.Lambda<TDelegate>(Expression.Not(expression.Body), expression.Parameters);
            }
            return expression;
        }

You can take a look at this question for more examples Is there any way to negate a Predicate? 您可以查看此问题以获取更多示例是否有任何方法可以否定谓词?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM