2011-03-03 113 views
106

在使用的EntityFramework,我得到的錯誤「A lambda expression with a statement body cannot be converted to an expression tree」,試圖編譯下面的代碼時:「與語句體lambda表達式不能轉換爲表達式樹」

Obj[] myArray = objects.Select(o => 
{ 
    var someLocalVar = o.someVar; 

    return new Obj() { 
    Var1 = someLocalVar, 
    Var2 = o.var2 }; 
}).ToArray(); 

我不不知道錯誤的含義,最重要的是如何解決它。任何幫助?

+3

嘗試轉換到列出這樣。 。objects.List()選擇(... – 2013-10-10 15:57:24

回答

0

Arr基本類型的Obj? Obj類是否存在?只有Arr是Obj的基本類型,您的代碼才能工作。你可以試試這個:

Obj[] myArray = objects.Select(o => 
{ 
    var someLocalVar = o.someVar; 

    return new Obj() 
    { 
     Var1 = someLocalVar, 
     Var2 = o.var2 
    }; 
}).ToArray(); 
4

不知道更多關於你在做什麼(?Linq2Objects,Linq2Entities,LINQ2SQL),這應該使其工作:

Arr[] myArray = objects.AsEnumerable().Select(o => { 
    var someLocalVar = o.someVar; 

    return new Obj() { 
     Var1 = someLocalVar, 
     Var2 = o.var2 
    }; 
}).ToArray(); 
+8

這迫使可查詢到評估 – smartcaveman 2011-03-03 10:32:55

+0

然而,在這種情況下它是好的,因爲他叫ToArray的()反正之後 – smartcaveman 2011-03-03 10:38:15

+2

不一定是 - 。誰知道有多大的「o 「是什麼?它可能有50種屬性,當我們想要的是2 – kdawg 2011-04-15 13:46:23

27

這意味着你不能在需要將lambda表達式轉換爲表達式樹(例如使用linq2sql時)的地方使用帶有「語句體」的lambda表達式(即使用花括號的lambda表達式)。

+17

你......稍微改寫了錯誤。@Tim羅傑斯的回答是更好 – vbullinger 2013-02-27 18:18:38

+4

+1定義什麼是‘語句體’是。 – TomNysetvold 2013-03-21 22:05:33

+1

@vbullinger你是對的程度,但在更普遍的意義(LINQ到SQL的上下文之外)這是一個更直接的答案。它幫助我與AutoMapper錯誤 – mlhDev 2014-12-30 15:52:40

69

objects Linq-To-SQL數據庫上下文嗎?在這種情況下,您只能在=>運算符的右側使用簡單的表達式。原因是,這些表達式並沒有被執行,而是被轉換爲SQL來針對數據庫執行。 嘗試此

Arr[] myArray = objects.Select(o => new Obj() { 
    Var1 = o.someVar, 
    Var2 = o.var2 
}).ToArray(); 
1

這意味着其含有([parameters]) => { some code };TDelegate類型的Lambda表達式不能被轉換爲Expression<TDelegate>。這是規則。

簡化查詢。您提供的一個可以改寫爲以下,將編譯:

Arr[] myArray = objects.Select(o => new Obj() 
       { 
        Var1 = o.someVar, 
        Var2 = o.var2 
       }).ToArray(); 
59

您可以使用的語句體在蘭巴表達式IEnumerable的集合。 試試這個:

Obj[] myArray = objects.AsEnumerable().Select(o => 
{ 
    var someLocalVar = o.someVar; 

    return new Obj() 
    { 
     Var1 = someLocalVar, 
     Var2 = o.var2 
    }; 
}).ToArray(); 

注意:
使用此方法時,因爲這樣一來,你將不得不在內存中的所有查詢結果仔細想想,可能對你的代碼的其餘部分不必要的副作用。

+3

+1我喜歡這個!'添加AsEnumerable()'maskes我的問題消失! – Joel 2013-07-09 11:40:32

+5

氏s是真正的解決方案,公認的答案是很難在某些情況下 – 2013-08-02 10:47:34

+8

不,這不是真正的答案申請。這會讓你的查詢在客戶端執行。請參考此問題的詳細信息:http://stackoverflow.com/questions/33375998/optimize-linq-to-sql-statement-that-has-foreign-key-access/33376119 – 2015-10-27 19:09:28

2

使用此重載的選擇:

Obj[] myArray = objects.Select(new Func<Obj,Obj>(o => 
{ 
    var someLocalVar = o.someVar; 

    return new Obj() 
    { 
     Var1 = someLocalVar, 
     Var2 = o.var2 
    }; 
})).ToArray(); 
+0

這適用於我,但與Entity Framework一起使用時,此解決方案會阻止dbcontext首先將所有行加載到內存中,就像AsEnumerable()那樣? – parliament 2014-11-23 21:57:52

+1

@議會:爲了防止加載所有行到內存中,你應該使用'Expression >'。 – Mohsen 2014-11-25 05:42:32

0

針對您的特殊情況下,身體被用於創建一個變量,並切換到IEnumerable將迫使所有的操作要在客戶端的處理,筆者建議解決方案

Obj[] myArray = objects 
.Select(o => new 
{ 
    SomeLocalVar = o.someVar, // You can even use any LINQ statement here 
    Info = o, 
}).Select(o => new Obj() 
{ 
    Var1 = o.SomeLocalVar, 
    Var2 = o.Info.var2, 
    Var3 = o.SomeLocalVar.SubValue1, 
    Var4 = o.SomeLocalVar.SubValue2, 
}).ToArray(); 

編輯:重命名爲C#編程約定

0

的LINQ to SQL的返回對象正在實施IQueryable接口。因此,對於Select方法謂詞參數,您應該只提供沒有主體的單個lambda表達式。

這是因爲LINQ的SQL代碼是不是裏面的程序,而不是遠程端如SQL Server或其他執行。此延遲加載執行類型是通過實施IQueryable的其中其期望委託被包裹在表達型類象下面實現。

Expression<Func<TParam,TResult>> 

的表達式樹不支持lambda表達式與身體和其與只支持單行lambda表達式像var id = cols.Select(col => col.id);

所以如果你試試下面的代碼將無法工作。

Expression<Func<int,int>> function = x => { 
    return x * 2; 
} 

以下內容將按預期工作。

Expression<Func<int,int>> function = x => x * 2;