2012-11-27 89 views
2

我開始與此:通Func鍵<>選擇

query 
    .Take(20) 
    .Select(item => new 
    { 
     id = item.SomeField, 
     value = item.AnotherField 
    }) 
    .AsEnumerable() 
    .ToDictionary(item => item.id, item => item.value); 

現在,我想重用的一切,除了SomeFieldAnotherField

public static Dictionary<int, string> ReusableMethod<T>(
    this IQueryable<T> query, 
    Func<T, int> key, 
    Func<T, string> value) 
{ 
    return query 
     .Take(20) 
     .Select(item => new 
     { 
      id = key(item), 
      value = value(item) 
     }) 
     .AsEnumerable() 
     .ToDictionary(item => item.id, item => item.value); 
} 

query.ReusableMethod(item => item.SomeField, item => item.AnotherField); 

這工作,但DB查詢選擇比需要更多的數據,所以我想這意味着ReusableMethod使用LINQ到對象。

是否有可能做到這一點,而只選擇需要的數據?我會補充一點,Func <>對我來說仍然是魔術,所以我可能會錯過一些明顯的東西。

澄清爲避免混淆:Take(20)是好的,Select()不是。

+1

所有字段因爲你'Func'調用不能在SQL進行評估,從而整個對象被選中,函數被調用的對象。 –

+0

@WillemDuncan你是否暗示這是不可能的,或者是否有辦法獲得理想的結果? – Stijn

回答

3

包裝你funcs中與Expression和刪除AsEnumerable電話。

public static Dictionary<int, string> ReusableMethod<T>(
    this IQueryable<T> query, 
    Expression<Func<T, int>> key, 
    Expression<Func<T, string>> value) 

另一種方法是隻返回整行。在這種情況下不需要Expression

return query 
    .Take(20) 
    .ToDictionary(key, value); 
+2

有關如何使用「選擇」中的選項的提示? 'key.Compile()(item)'讓我回到原點。 – Stijn

+0

它應該只是工作。無需調用「編譯」。 –

+1

然後我不知道正確的語法。用'Expression'包裝它們是不夠的。 – Stijn

1

最近,我有同樣的問題,這裏是我做過什麼:

  1. 你有一些DbEntity(通過LINQ產生的EF,SQL),但你要查詢只有某些領域(我這樣做是爲了節省網絡帶寬)。你必須創建DbEntity派生類,怎麼一回事,因爲你不能創造表達式樹anonyous類型,你不能在select語句創建DbEntity的新實例。 (無需添加任何字段,屬性等)

    公共類LocalEntity:DbEntity {}

  2. 您需要定義生成您的選擇表達式樹的方法。它應該看起來像這樣。這將生成表達式樹類似:。選擇(分貝=>新LocalEntity(){Property1 = db.Property1,Proeprty2 = db.Property2})

    protected Expression<Func<DbEntity, LocalEntity>> getSelectExpression() 
    { 
        ParameterExpression paramExpr = Expression.Parameter(typeof(DbEntity), "dbRecord"); 
        var selectLambda = Expression.Lambda<Func<DbEntity, LocalEntity>>(
             Expression.MemberInit(
              Expression.New(typeof(LocalEntity)), 
              Expression.Bind(typeof(LocalEntity).GetProperty("DbEntityFieldName"), Expression.Property(paramExpr, "DbEntityFieldName"), 
              .... 
              )) 
             ), 
             paramExpr); 
    
        return selectLambda; 
    } 
    
  3. 使用方法如下:

    query.Select(getSelectExpression())ToDictionary();

考慮這更是僞代碼比C#代碼,我不得不把它簡化很多,我不能測試,但如果奧尤使它的工作,它將從DB只傳輸字段定義在getSelectedExpression中,不是整行。選擇

相關問題