You are appending your OR in the wrong place. What you are doing now is effectively the something like this:
(from t in Context.Table1
where identifiers.Contains(t.Id)
select t)
OR
(where identifiers.Contains(t.CanceledId))
The second problem is that the BuildContainsExpression method you use, returns a lambda expression, something that looks like this:
t => t.Id == 1 || t.Id == 2 || ...
You can't change this expression once it's generated. However, that's what you want because you'd like to have something like this:
t => t.Id == 1 || t.Id == 2 || ... || t.CanceledId == 1 || t.CanceledId == 2 || ...
You can't simply take the body of this lambda expression and or it together with another expression because it depends on the parameter t.
So what you can do is the following:
// 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));
Your if statement would now look like this:
if (!showCanceled)
{
// Use original version of BuildContainsExpression.
}
else
{
// Create some expressions and use overloaded version of BuildContainsExpression.
}