1

I am trying to figure out how the Predicates work. I have a piece of code where one parameter will always be supplied but there could be up to 5 different parameters.

If I try this way

var predicate = PredicateBuilder.False<Data.AccountAllocation>();                  

if (startDate.HasValue)
   predicate = predicate.And(p => p.DateEntered >= startDate);

if (endDate.HasValue)
   predicate = predicate.And(p => p.DateEntered <= endDate);

if (allocationTypeId.HasValue)
    predicate = predicate.And(p => p.AllocationTypeID == allocationTypeId);

if (allocationStatusID.HasValue)
    predicate = predicate.And(p => p.AllocationStatusTypeID == allocationStatusID);

var accountAllocation = await db.AccountAllocations.AsExpandable().Where(predicate).ToListAsync();

return accountAllocation;

It returns nothing yet if I write it this way

var predicate = PredicateBuilder.False<Data.AccountAllocation>();

if (accountId > 0)
   predicate = predicate.Or(p => p.AccountID == accountId);

if (startDate.HasValue)
   predicate = predicate.And(p => p.DateEntered >= startDate);

if (endDate.HasValue)
   predicate = predicate.And(p => p.DateEntered <= endDate);

if (allocationTypeId.HasValue)
   predicate = predicate.And(p => p.AllocationTypeID == allocationTypeId);

if (allocationStatusID.HasValue)
   predicate = predicate.And(p => p.AllocationStatusTypeID == allocationStatusID);

var accountAllocation = await db.AccountAllocations.AsExpandable().Where(predicate).ToListAsync();

return accountAllocation;

It works properly. If I change the first Predicate, the account, from .Or to .And it does not work.

.Or always seems to run but if I put .Or for all of them the date returned is not correct since it needs to be an .And

I am trying to figure out how to get this to work because there will be a time where all the parameters are optional. and I will not be able to use a .Or, what is the secret to getting the .And to work regardless oh how many of the parameters get added.

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
Luckbox72
  • 147
  • 1
  • 2
  • 16

1 Answers1

1

If you only evaluate And conditions you must start with a True predicate, basically because false && bool1 && bool2 ... always evaluates to false:

var predicate = PredicateBuilder.True<Data.AccountAllocation>();

But when there is an Or predicate in the chain of predicates the expression becomes true if the Or predicate evaluates to true.

You probably start with a False predicate because you don't want to return any data of not a single parameter is entered. You can achieve this by checking the predicate at the end:

var predicate = PredicateBuilder.True<Data.AccountAllocation>();
var initString = predicate.ToString();

if (startDate.HasValue)
   predicate = predicate.And(p => p.DateEntered >= startDate);

...

if (predicate.ToString() == initString)
    predicate = predicate.And(p => false);
Gert Arnold
  • 105,341
  • 31
  • 202
  • 291