我正在尝试为Or表达式写一个静态函数,但收到以下错误:
参数'item'不在范围内。
描述:未处理的异常 在执行期间发生 当前的网络请求。请查看 堆栈跟踪以获取更多信息 错误及其来源 代码。
异常详细信息: System.InvalidOperationException:The 参数'item'不在范围内。
方法:
public static Expression<Func<T, bool>> OrExpressions(Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
// Define the parameter to use
var param = Expression.Parameter(typeof(T), "item");
var filterExpression = Expression.Lambda<Func<T, bool>>
(Expression.Or(
left.Body,
right.Body
), param);
// Build the expression and return it
return (filterExpression);
}
修改:添加更多信息
正在或将来的表达式来自下面的方法,执行得很好。如果有更好的方法或结果我都是耳朵。另外,我不知道有多少人提前或正在等待。
public static Expression<Func<T, bool>> FilterExpression(string filterBy, object Value, FilterBinaryExpression binaryExpression)
{
// Define the parameter to use
var param = Expression.Parameter(typeof(T), "item");
// Filter expression on the value
switch (binaryExpression)
{
case FilterBinaryExpression.Equal:
{
// Build an expression for "Is the parameter equal to the value" by employing reflection
var filterExpression = Expression.Lambda<Func<T, bool>>
(Expression.Equal(
Expression.Convert(Expression.Property(param, filterBy), typeof(TVal)),
Expression.Constant(Value)
),
param);
// Build the expression and return it
return (filterExpression);
}
修改:添加更多信息
或者,是否有更好的方法来做或?目前.Where(约束)在约束为Expression&gt;类型的情况下工作得很好。我该怎么做(constraint1或constraint2)(到约束n'th)
提前致谢!
答案 0 :(得分:9)
问题是您在方法OrExpressions中创建的表达式会重用两个表达式的主体。这些实体将包含对它们自己的ParameterExpression的引用,该引用已在FilterExpression中定义。
修复方法是重写左右部分以使用新的ParameterExpression。或者传递原始的ParameterExpression。这不是因为两个ParameterExpression具有相同的名称,它们代表相同的参数。
答案 1 :(得分:5)
正如已经建议的那样,here你可以找到这个非常好的(工作)代码
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>(Expression.Or(expr1.Body, invokedExpr), expr1.Parameters);
}
您可以适应您的需求,并且不与LINQ绑定(恕我直言)。
答案 2 :(得分:2)
我不确定这里的正确术语,但基本上表达式参数不相同,即使它们具有相同的名称。
这意味着
var param1 = Expression.Parameter(typeof(T), "item");
var param2 = Expression.Parameter(typeof(T), "item");
param1 != param2
如果在表达式中使用,param1和param2将不会是同一个东西。
处理此问题的最佳方法是为表达式预先创建一个参数,然后将其传递给需要该参数的所有辅助函数。
编辑:另外,如果您尝试动态编写LINQ中的where子句,可以尝试PredicateBuilder。
答案 3 :(得分:2)
对于那些通过搜索引擎找到此页面并将使用 Ben&amp; Joe Albahari的PredicateBuilder 的人,请注意,因为不适用于实体框架< /强>
答案 4 :(得分:1)
Fabrizio的解决方案也出现在我身上,但由于我试图将两个表达式组合起来,这些表达式将作为linq 2 sql查询执行,我认为它将在内存而不是sql server中执行。
我写了 - Linq-To-Sql认识到调用是lambda表达式,因此仍然会生成优化的sql。