0

I have this predciate, I would like build it with linqkit because the predicate can change depending of options.

.Where(p => p.FirstName == "John" && p.LastName == "Doe" && ((p.Age > 30 || p.Status >= 10)));

I tried :

var predicate = PredicateBuilder.New<Person>();
var orPredicate = PredicateBuilder.New<Person>();

orPredicate.Or(p => p.Age > 30);
orPredicate.Or(p => p.Status >= 10);

Predicate.And(p => p.FirstName == "John");
Predicate.And(p => p.LastName == "Doe");

predicate = predicate.Or(orPredicate);
myQueryable = myQueryable.Where(predicate);

When I do this the result is like a "Or" between each(4) conditions. Am I missed something?

Thanks,

Fildor
  • 14,510
  • 4
  • 35
  • 67
TheBoubou
  • 19,487
  • 54
  • 148
  • 236
  • 1
    Not familiar with PredicateBuilder nor Linqkit, but I would have thought `predicate = predicate.Or(orPredicate);` needs to be `predicate = predicate.And(orPredicate);` – Fildor Jun 05 '23 at 10:18
  • @Fildor I tried this ut it's like and I have a AND between all conditions – TheBoubou Jun 05 '23 at 10:26
  • 1
    I think this doesn't work as intuitively as I thought: see https://github.com/scottksmith95/LINQKit#nesting-predicates has an example that's pretty similar to your usecase. – Fildor Jun 05 '23 at 10:36
  • 2
    I think the problem is `LinqKit` uses fluent syntax, meaning it returns modified object as a result. See https://dotnetfiddle.net/LAFl56 for updated code that I think does what you intended. – orhtej2 Jun 05 '23 at 10:38
  • ^^ Yes, that might be it. Your code dismisses some of the changes. – Fildor Jun 05 '23 at 10:39
  • 1
    [`And`](https://github.com/scottksmith95/LINQKit/blob/9092e0144925ec75c32f2616d633bbcb0a99be2c/src/LinqKit.Core/PredicateBuilder.cs#L109) is even attributed [`[Pure]`](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.contracts.pureattribute?view=net-7.0) meaning it does not modify builder's state. – orhtej2 Jun 05 '23 at 10:42

1 Answers1

2

Looking at the docs, I think your snippet can be fixed like so:

var predicate = PredicateBuilder.New<Person>();
var orPredicate = PredicateBuilder.New<Person>();

orPredicate = orPredicate.Start(p => p.Age > 30);
orPredicate = orPredicate.Or(p => p.Status >= 10);

predicate = predicate.Start(p => p.FirstName == "John");
predicate = predicate.And(p => p.LastName == "Doe");

predicate = predicate.And(orPredicate);
myQueryable = myQueryable.Where(predicate);

Mind that I have Zero experience with LinqKit and derived this just from referenced docs.

Fildor
  • 14,510
  • 4
  • 35
  • 67