2014-11-24 68 views
0

我有實體,例如CategoryEntity,RubricEntity,CityEntity等 我需要顯示這些實體的下拉菜單。這個實體具有不同的屬性。 所有這些我需要轉換爲DropDownListItem顯示爲下拉,所以我覺得我可以用這樣的方法與DB工作,但我得到異常使用方法中的Lambda表達式的DropDownListItem的實體

的LINQ表達式節點類型「調用」不是在LINQ支持到實體。

public static IQueryable<DropDownListItem> ToDropDownList<TSource>(IQueryable<TSource> query, Expression<Func<TSource, long>> value, Expression<Func<TSource, string>> text) 
     { 
      var valueLambda = value.Compile(); 
      var textLambda = text.Compile(); 

      return query.Select(x => new DropDownListItem 
      { 
       Value = (long) valueLambda(x), 
       Text = (string) textLambda(x) 
      }); 
     } 

我認爲我可以使用這樣的事情了,但不知道如何使用表達式和lambda它做。

其結果是我想要的東西,像

ToDropDownList2<RubricEntity>(_service.RubricAsQueryable(), x => x.Id, x => x.DisplayName) 

回答

0

的問題是,LINQ到實體不支持編譯表情,而你編譯表達和試圖調用它們。但是,LINQ試圖將它們解析爲表達式並將它們轉換爲SQL代碼,並且它不能這樣做。 而你想通過textvalue作爲不同的參數,所以你不能合併它們。

你可以這樣做:

public static IQueryable<DropDownListItem> ToDropDownList<TSource>(IQueryable<TSource> query, Expression<Func<TSource, DropDownListItem>> value) 
{ 
    return query.Select(value); 
} 

ToDropDownList<RubricEntity>(_service.RubricAsQueryable(), x => new DropDownListItem() { Value = x.Id, Text = x.DisplayName }); 

但對於我來說,這has't有很大的意義...

如果你仍然想通過他們作爲獨立的參數,那麼你就可以嘗試在運行時將它們結合起來是這樣的:

public static IQueryable<DropDownListItem> ToDropDownList<TSource>(IQueryable<TSource> query, Expression<Func<TSource, long>> value, Expression<Func<TSource, string>> text) 
{ 
    Expression<Func<TSource, DropDownListItem>> func = x => new DropDownListItem 
    { 
     Value = 1, 
     Text = "1" 
    }; 


    var replacer = new ExpressionReplacer<TSource>() 
        { 
         Text = text, 
         Value = value, 
         Parameter = func.Parameters[0] // we will take X parameter 

        }; 
    var convertedFunc = replacer.Visit(func) as Expression<Func<TSource, DropDownListItem>>; 

    return query.Select(convertedFunc); 
} 


private class ExpressionReplacer<TSource> : ExpressionVisitor 
{ 
    public Expression<Func<TSource, long>> Value { get; set; } 
    public Expression<Func<TSource, string>> Text { get; set; } 
    public ParameterExpression Parameter { get; set; } 

    protected override Expression VisitConstant(ConstantExpression node) 
    { 
     if (node.Type == typeof(long)) 
      return this.Visit(Value.Body); 
     if (node.Type == typeof(string)) 
      return this.Visit(Text.Body); 
     return base.VisitConstant(node); 
    } 

    protected override Expression VisitParameter(ParameterExpression node) 
    { 
     // we will replace all usage to X. it has the same type, but it isn't linked to expiression 
     return Parameter; 
    } 
} 

ToDropDownList<RubricEntity>(_service.RubricAsQueryable(), x => x.Key, x => x.Value); 

基本上我們剛創建的常量值存根表達,然後根據不同類型隨附在paremeters表達式替換常數值。然後發送替換表達式選擇的方法,所以它finaly表達式將類似於:

Select(x => new DropDownListItem() { Value = x.Id, Text = x.DisplayName }) 
+0

您好我得到了這樣的錯誤「X」未在指定的LINQ到實體綁定的參數查詢表達式。感謝您的幫助。 – 2014-11-25 10:58:26

+0

關於如何解決這個問題的任何想法? – 2014-11-25 19:30:37

+0

嗨。嗯你是對的。我更新了'ExpressionReplacer'的答案,並輕微更改了'ToDropDownList'方法。我用EF本地檢查它,它工作正常。 – 2014-11-25 22:36:13

相關問題