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.
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);