LINQKit
LINQKit copied to clipboard
PredicateBuilder changes predicate itself, not only returned value
Using LinqKit.Microsoft.EntityFrameworkCore, Version=1.1.15.0
The following code should leave basePredicate with only "true" and newPredicate with "true and Property = someValue".
var basePredicate = PredicateBuilder.New<SomeClass>(true);
var newPredicate = basePredicate.And(x => x.Property == someValue);
However basePredicate is changed itself to "true and Property = someValue", so it is not only returning the new expression, it is changing the original. This certainly not the case in older (.Net 4.x + EF6) versions.
It seems this it not known? All examples still mention returning a value but in the following example basePredicate has no need to return anything as it is updated by itself.
var basePredicate = PredicateBuilder.New<SomeClass>(true);
basePredicate.And(x => x.Property == someValue);
Or Documentation should mention this? Or this is undesired behavior?
PredicateBuilder.New() returns an ExpressionStarter<T>. This object provides some cool features.
- You can know if the predicate is started or not. Since we know now if the expression is started, we can decided to not even call the predicate if we don't need too.
if (starter.IsStarted)
{ // execute something using predicate }
- You an still cast it away if you don't use var :
Expression<Func<SomeClass, bool>> basePredicate = starter; // Casts away ExpressionStarter
- Before ExpressionStarter<T>, you would get garbage query to start: x => true (1=1) or x=>false (1=0), and then you had to call either And() or Or() to add to it and reassign the variable. Two of the options aren't even valid. And the final predicate shouldn't include them if we don't want them.
- Expressions are immutable, so before ExpressionStarter, a developer had to handle the re-assignment themselves.
foreach (/* some loop */)
expressionToBuild = expressionToBuild.And(/* some other expression */); // or Or()
ExpressionStarter now handles that re-assignment of the immutable expression for you.
var expressionToBuild = PredicateBuilder.New<SomeClass>(); // Returns an ExpressionStarter<SomeClass> which is hold the immutable Expression inside it. It acts as if it were an Expression<Func<SomeClass, bool>>, but it is not.
foreach (/* some loop */)
expressionToBuild.And(/* some other expression */); // or Or()