【问题标题】:Expression.Or, The parameter 'item' is not in scopeExpression.Or,参数“item”不在范围内
【发布时间】:2009-01-04 21:44:31
【问题描述】:

我正在尝试将静态函数写入或两个表达式,但收到以下错误:

参数“item”不在范围内。

描述:未处理的异常 在执行过程中发生 当前的网络请求。请查看 堆栈跟踪以获取有关的更多信息 错误及其起源 代码。

异常详情: System.InvalidOperationException: 参数“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);
}

编辑:添加更多信息

or'd 的表达式来自下面的方法,执行得很好。如果有更好的方法或结果我全神贯注。另外,我不知道有多少被提前或被淘汰。

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(constraint) 在约束类型为 Expression> 的情况下工作得很好。我该怎么做 where(constraint1 or constraint2) (到约束 n'th)

提前致谢!

【问题讨论】:

    标签: c# linq expression-trees expression


    【解决方案1】:

    问题在于您在 OrExpressions 方法中创建的表达式重用了两个表达式的主体。这些主体将包含对它们自己的 ParameterExpression 的引用,该 ParameterExpression 已在 FilterExpression 中定义。

    解决方法是重写左右部分以使用新的 ParameterExpression。或者传递原始的 ParameterExpression。并不是因为两个ParameterExpression同名就代表同一个参数。

    【讨论】:

    • 谢谢!现在尝试传递相同的参数
    • 你我的朋友,太棒了:)
    【解决方案2】:

    正如已经建议的那样,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 无关(恕我直言)。

    【讨论】:

    • 小心,因为此代码不适用于实体框架。请参阅我的答案以获取固定版本。
    【解决方案3】:

    我不确定这里的正确术语,但基本上表达式参数即使名称相同也不等价。

    也就是说

    var param1 = Expression.Parameter(typeof(T), "item");
    var param2 = Expression.Parameter(typeof(T), "item");
    
    param1 != param2
    

    如果在表达式中使用,param1 和 param2 将不是同一个东西。

    解决此问题的最佳方法是为您的表达式预先创建一个参数,然后将其传递给所有需要该参数的辅助函数。

    编辑:另外,如果您尝试在 LINQ 中动态编写 where 子句,您可以试试 PredicateBuilder

    【讨论】:

    • 谢谢 :) 我重新设计了方法,将相同的参数传递给助手的方法,一切又好了。我正在研究 PredicateBuilder 以希望能清理干净
    • 小心,因为 Ben&Joe Albahari 的 PredicateBuilder 不适用于实体框架。请参阅我的答案以获取固定版本。
    【解决方案4】:

    对于那些通过搜索引擎找到此页面并打算使用 Ben&Joe Albahari 的 PredicateBuilder 的用户,请注意,因为它不适用于实体框架.

    改用this fixed version

    【讨论】:

      【解决方案5】:

      我也想到了 Fabrizio 的解决方案,但由于我试图组合两个将作为 linq 2 sql 查询执行的表达式,我认为它会在内存中执行,而不是在 sql 服务器中执行。

      我被写了 - Linq-To-Sql 识别出调用是一个 lambda 表达式,因此仍然会产生优化的 sql。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多