我正在使用EF 5来执行需要多个Where
条件的选择。
其中一个条件是仅包含Code
字段位于UI提供的代码列表中的记录(例如SQL翻译:{{1}})。
为实现这一目标,我构建了一个基于this post的表达式树,代码为:
AND Code IN (123, 456)
代码用作:
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);
}
当// 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);
大小合理时,这非常有效。但是,当列表包含超过1000个代码时,我会在desiredCodes
迭代器被评估的时刻得到StackOverflowException
。
问题
是否有其他方法可以实现不易受StackOverflowException攻击的 Contains 要求?
SQL(SQL Server 2012)生成的SQL大小是否有上限?
答案 0 :(得分:0)
我们遇到了同样的问题,在我分析了bug之后,到目前为止唯一的解决方法是手动编写查询(例如,通过string.Join()或其他东西生成IN(...),因为EF似乎通过递归遍历表达式来构建语句。