2011-12-15 34 views
2

因此,我收到了標題中的錯誤。我會直接跳到相關的代碼。首先,手動創建where語句(它的工作),然後動態創建不起作用。兩者都創建相同的queryExpression。當創建where子句時,動態創建LINQ「's不在範圍內」

首先,用這兩種方法所產生的queryExpression:

{Table(Products).Select 
    (s => new SalesData() { 
    ProductID = s.ProductID, 
    StoreName = s.StoreName, 
    Count = s.Count 
}).Where(s => (s.Count > 500))} 

現在,沒有工作的手動方法:

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 
           }); 

可正常工作;我的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 
           }); 

是唯一不同的是,在第二個片段,我動態創建lambda表達式。我已經注意到它在第二個片段中失敗的地方。

使用調試器我可以看到數據的queryExpression,這兩個方法都是一樣的,所以我不認爲我的問題是與我的實際表達式創建。如果需要該代碼,我可以在這裏發佈。

我的問題是,我做錯了什麼,我該如何解決它?

編輯: 這裏是給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; 
} 

內部過濾器,我有:

this.Predicate = BuildPredicate.GetPredicate(this.filterList, this.PE); 

this.PE是:

public ParameterExpression PE 
{ 
    get 
    { 
     return Expression.Parameter(typeof(SalesData), "s"); 
    } 
} 
+1

`filter.Predicate`的類型和值是什麼?還請注意,僅僅因爲兩個lambda參數被調用相同,它們與表達式的角度不同... – SWeko 2011-12-15 14:23:44

+0

filter.Predicate是類型表達式和調試器說值是{(s.Count> 500)} – 2011-12-15 14:28:35

回答

0

由於本頁上的對話框和使用Predicate Builder,我能夠解決我的問題。

我想要做的更好的方法可以在Scott Gu's site找到。這對我的目的更好,因爲我需要動態確定字段和值,並允許分組(使用此方法更容易)。

5

來自C#的父親,Anders Hejlsberg:

參數在表達式中通過其對象標識引用,而不是通過比較它們的名稱。實際上,從表達樹的角度來看,參數的名稱純粹是信息性的。這種設計的原因與通過System.Type對象引用類型的原因相同,而不是它們的名稱 - 表達式樹完全綁定,並且不在實現名稱查找規則的業務中(這可能會因語言而異) 。

From MSDN Forums

短期和長期的它是filter.Predicate{(s.Count > 500)}值,但這並不意味着s已經與最初的LINQ表達共享一個名字,意思是在這裏。