Вы добавляете свое ИЛИ не в том месте. То, что вы делаете сейчас, фактически выглядит примерно так:
(from t in Context.Table1
where identifiers.Contains(t.Id)
select t)
OR
(where identifiers.Contains(t.CanceledId))
Вторая проблема заключается в том, что используемый вами метод BuildContainsExpression
возвращает лямбда-выражение, которое выглядит примерно так:
t => t.Id == 1 || t.Id == 2 || ...
Вы не можете изменить это выражение, как только оно сгенерировано. Тем не менее, это то, что вы хотите, потому что вы хотели бы иметь что-то вроде этого:
t => t.Id == 1 || t.Id == 2 || ... || t.CanceledId == 1 || t.CanceledId == 2 || ...
Вы не можете просто взять тело этого лямбда-выражения и / или его вместе с другим выражением, потому что оно зависит от параметра t
.
Итак, вы можете сделать следующее:
// Overload of BuildContainsExpression.
private static Expression<Func<T, bool>> BuildOtherContainsExpression<T>(
ParameterExpression p, Expression field1, Expression field2, int[] values)
{
var eq1 = values.Select(v => Expression.Equal(field1, Expression.Constant(v)));
var eq2 = values.Select(v => Expression.Equal(field2, Expression.Constant(v)));
var body = eq1.Aggregate((acc, equal) => Expression.Or(acc, equal));
body = eq2.Aggregate(body, (acc, equal) => Expression.Or(acc, equal));
return Expression.Lambda<Func<T, bool>>(body, p);
}
// Create a parameter expression that represents something of type Table1.
var parameter = Expression.Parameter(typeof(Table1), "t");
// Create two field expressions that refer to a field of the parameter.
var idField = Expression.Property(parameter, "Id");
var canceledIdField = Expression.Property(parameter, "CanceledId");
// And finally the call to this method.
query.Where(BuildContainsExpression<Table1>(
parameter, idField, canceledIdField, identifiers));
Ваше утверждение if теперь будет выглядеть так:
if (!showCanceled)
{
// Use original version of BuildContainsExpression.
}
else
{
// Create some expressions and use overloaded version of BuildContainsExpression.
}