I'm using EF 5 to perform a select requiring a multitude of Where
conditions.
One of those conditions is to include only records where a Code
field is in a list of codes provided by the UI (e.g. SQL translation: AND Code IN (123, 456)
).
To achieve that, I build an expression tree based on this post, with the code:
static public Expression<Func<TElement, bool>>
BuildContainsExpression<TElement, TValue>(
Expression<Func<TElement, TValue>> valueSelector,
IEnumerable<TValue> values)
{
if (null == valueSelector)
{
throw new ArgumentNullException("valueSelector");
}
if (null == values) { throw new ArgumentNullException("values"); }
ParameterExpression p = valueSelector.Parameters.Single();
if (!values.Any())
{
return e => false;
}
var equals =
values.Select(value => (Expression)Expression.Equal(
valueSelector.Body,
Expression.Constant(value, typeof(TValue))));
var body =
equals.Aggregate<Expression>((accumulate, equal) =>
Expression.Or(accumulate, equal));
return Expression.Lambda<Func<TElement, bool>>(body, p);
}
The code is used like:
// List<long> desiredCodes is provided by the UI
containsExpression = LinqToEntitiesUtil.BuildContainsExpression<MyClass, long>
(my => my.Code, desiredCodes);
// In the actual code there are several other Where conditions as well
var matching = ctx.MyClasses.Where(containsExpression).Select(my => my);
This works perfectly when desiredCodes
is reasonably sized. However, when the list contains a little over 1000 codes, I get a StackOverflowException
the moment the matching
iterator is evaluated.
Questions
Is there another way to implement the Contains requirement that is not vulnerable to a StackOverflowException?
Is there an upper limit on the size of the generated SQL imposed by SQL (SQL Server 2012)?