IQueryable.QueryProvider.CreateQuery异常:“参数表达式无效”

时间:2012-02-24 09:10:21

标签: c# linq

下面的代码是在T的Generic类中继承自List - 因此为什么我对该对象一无所知以及为什么我将列名传递给该方法。

Exception几乎出现在该方法的最后一行。

 public decimal? Max (string column) 
    {
        IQueryable<T> queryableData = this.AsQueryable<T>();

        // Compose the expression tree that represents the parameter to the predicate.
        ParameterExpression pe = Expression.Parameter(typeof(T), "item");

        // ***** Select(item => item.[column]) *****
        // Create an expression tree that represents the expression 'item.[column] == "id"'
        Expression left = null;
        try
        {
            left = Expression.Property(pe, typeof(T).GetProperty(column, System.Type.EmptyTypes));
        }
        catch
        {
        }

        // Create an expression tree that represents the expression
        // 'queryableData.Select(item => item.[column]) '
        MethodCallExpression whereCallExpression = null;
        try
        {
            whereCallExpression = Expression.Call(
                typeof(Queryable),
                "Select",
                new Type[] { queryableData.ElementType, typeof(int) },
                queryableData.Expression,
                Expression.Lambda<Func<T, int>>(left, new ParameterExpression[] { pe }));

        }
        catch
        {
        }
        IQueryable<T> results = null;

            string lexpression = whereCallExpression.ToString();
            // Create an executable query from the expression tree.

            //Exception at this line of Code:
             results= queryableData.Provider.CreateQuery<T>(whereCallExpression);

        return Convert.ToInt32(results.Max());
    }

传入的表达式(即whereCallEWxpression)看起来是正确的,但是这个异常不断出现:“参数表达式无效”。我真的陷入困境,无法找到解决方案。

此外,如果有人知道更好的方法来实现这一点,请让我知道 - 我能想到的一切。

谢谢,

罗伯特

编辑: whereCallExpression的构造可能是错误的。那么问题是如何解决它。这真的是我无法理解的困难。

编辑2:尝试删除catch块 - 仅用于调试目的。

2 个答案:

答案 0 :(得分:2)

要回答“更好的实现方法”,并假设您在计算Max时知道T是什么,为什么不使用内置的IEnumerable.Max()扩展方法?假设您的类继承自List<T>,因为您似乎在说问题的开头,这应该可行:

var myClass = new YourClass<Person>(); // obviously this would have been initialized and filled elsewhere
var maxAge = myClass.Max(p => p.Age); //Assuming Person has an Age property

如果你真的需要在课堂上这样做,你可以在课堂上做这样的事情(未经测试的代码):

public class myClass<T> : List<T> {
    private readonly Func<T, decimal> _fieldGetter;

    public myClass(Func<T, decimal> fieldGetter) {
         _fieldGetter = fieldGetter;
    }

    // then your Max becomes:
    public decimal? Max() {
        return this.Max(i => _fieldGetter(i));
    }
}

答案 1 :(得分:0)

解决!!

答案就在我面前......感谢Chris Shain让我走上正轨

var result =this.Select(c => c.GetType().GetProperty(column).GetValue(c, null));

return (int)result.Max();