Предикаты LinqKit

Я пытаюсь понять, как работают предикаты. У меня есть фрагмент кода, в котором всегда будет указан один параметр, но может быть до 5 разных параметров.

Если я попробую так

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;

Пока ничего не возвращает, если я напишу это так

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;

Он работает правильно. Если я изменю первый предикат, учетную запись, с .Or на .И это не сработает.

.Or всегда работает, но если я поставлю .Or для всех из них, возвращаемая дата неверна, так как она должна быть .And

Я пытаюсь понять, как заставить это работать, потому что будет время, когда все параметры будут необязательными. и я не смогу использовать .Или, в чем секрет получения .И работать независимо от того, сколько параметров добавлено.


person Luckbox72    schedule 28.04.2015    source источник


Ответы (1)


Если вы оцениваете только And условия, вы должны начать с предиката True, в основном потому, что false && bool1 && bool2 ... всегда оценивается как false:

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

Но когда в цепочке предикатов есть предикат Or, выражение становится true, если предикат Or оценивается как true.

Вы, вероятно, начинаете с предиката False, потому что вы не хотите возвращать какие-либо данные, если не введен ни один параметр. Вы можете добиться этого, проверив предикат в конце:

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);
person Gert Arnold    schedule 28.04.2015