在动态创建where子句时,LINQ"'不在范围内"

Joh*_*arr 3 c# lambda expression-trees linq-to-sql

所以,我收到了标题中的错误.我将直接进入相关代码.首先,手动创建where语句(确实有效),然后动态创建不起作用.两者都创建相同的queryExpression.

首先,使用两种方法生成的queryExpression:

{Table(Products).Select
  (s => new SalesData() {
    ProductID = s.ProductID,
    StoreName = s.StoreName, 
    Count = s.Count
}).Where(s => (s.Count > 500))}
Run Code Online (Sandbox Code Playgroud)

现在,工作的手动方法:

IQueryable<SalesData> data = ( from s in sales.Products
                               select new SalesData
                               {
                                   ProductID = s.ProductID,
                                   StoreName = s.StoreName,
                                   Count = s.Count
                               } ).AsQueryable<SalesData>();

data = data.Where(s => s.Count > 500);

this.dataGridView1.DataSource = null;

this.dataGridView1.DataSource = (from d in data
                                 select new
                                 {
                                     d.ProductID,
                                     d.StoreName,
                                     d.Count
                                 } );
Run Code Online (Sandbox Code Playgroud)

这按预期工作; 我的DataGridView填充了数据.

现在,动态创建where子句:

IQueryable<SalesData> data = ( from s in sales.Products
                               select new SalesData
                               {
                                   ProductID = s.ProductID,
                                   StoreName = s.StoreName,
                                   Count = s.Count
                               } ).AsQueryable<SalesData>();

if (this.filter.Predicate != null)
{
    Expression<Func<SalesData, bool>> lambda =
        Expression.Lambda<Func<SalesData, bool>>(this.filter.Predicate,
            new ParameterExpression[] { this.filter.PE });

    data = data.Where(lambda);
}

this.dataGridView1.DataSource = null;

this.dataGridView1.DataSource = (from d in data  <---- fails here
                                 select new
                                 {
                                     d.ProductID,
                                     d.StoreName,
                                     d.Count
                                 } );
Run Code Online (Sandbox Code Playgroud)

唯一不同的是,在第二个片段中,我正在动态创建lambda表达式.我已经注意到它在第二个片段中失败了.

使用调试器我可以看到queryExpression for data和两种方法都是一样的,所以我认为我的问题不在于我的实际表达式创建.如果需要该代码,我可以在这里发布.

我的问题是,我做错了什么,我该如何解决?

编辑: 这是给filter.Predicate它的值的函数:

public static Expression GetPredicate(List<FilterItem> itemList, ParameterExpression pe)
{
    List<Expression> expressions = new List<Expression>();
    List<string> combiners = new List<string>();

    foreach (FilterItem item in itemList)
    {
        Expression left = Expression.PropertyOrField(pe, item.Field);
        Expression right = Expression.Constant(Convert.ToInt32(item.Value), typeof(int));

        expressions.Add(Expression.GreaterThan(left, right));
        combiners.Add(item.Combiner);
    }

    int expressionCount = expressions.Count();
    Expression predicateBody = expressions[0];

    if (expressionCount > 1)
    {
        for (int x = 1; x <= expressionCount; x++)
        {
            switch (combiners[x - 1])
            {
                case "AND":
                    predicateBody = Expression.And(predicateBody, expressions[x]);
                    break;
                case "OR":
                    predicateBody = Expression.Or(predicateBody, expressions[x]);
                    break;
                default:
                    break;
            }
        }
    }

    return predicateBody;
}
Run Code Online (Sandbox Code Playgroud)

内部过滤器我有:

this.Predicate = BuildPredicate.GetPredicate(this.filterList, this.PE);
Run Code Online (Sandbox Code Playgroud)

this.PE是:

public ParameterExpression PE
{
    get
    {
        return Expression.Parameter(typeof(SalesData), "s");
    }
}
Run Code Online (Sandbox Code Playgroud)

doc*_*ess 5

来自C#的父亲,Anders Hejlsberg:

表达式通过对象标识引用参数,而不是通过比较它们的名称.实际上,从表达式树的角度来看,参数的名称纯粹是信息性的.这种设计的原因与通过System.Type对象而不是它们的名称引用类型的原因相同 - 表达式树是完全绑定的,并且不在实现名称查找规则(可能因语言而异)中. .

来自MSDN论坛

它的长短filter.Predicate有一个值,{(s.Count > 500)}但这并不意味着s通过与初始LINQ表达式共享一个名称而具有意义.