2009-09-21 73 views
2

我一直在少數項目上使用linq2sql,但我決定是時候嘗試EF,因爲它應該是更強大和更好。有幾件事情真的很煩人。 其中之一是將結果投影到列表中,這在l2sql中效果很好,但在EF中效果不佳。entity-framework,如何投影到列表

public class bo.Transaction 
{ 
    public long Id { get; set; } 
    public List<bo.Line> Lines { get; set; } 
} 

public class bo.Line 
{ 
    public int RowNo { get; set; } 
    public string Descripton{ get; set; } 
    public double Amount{ get; set; } 
} 

return from t in Db.Transaction.Include("Lines") 
     select new bo.Transaction { 
     Id = t.Id, 
     Lines = t.Lines.OrderBy(l => l.RowNo).ToList(), 
     }; 

的ToList()調用但是失敗,與消息「System.NotSupportedException:LINQ實體無法識別方法‘列表[bo.Line] ToListLine’方法,和這種方法不能被翻譯成一家商店的表達。「」。

任何方法來解決這個問題?或者我只需要使用ienumerable而不是列表?

+0

一般來說,只要有可能,總是比較喜歡IList <>到List <>。 – 2009-09-21 13:48:23

回答

0

這是一個在黑暗中刺,但你的項目有一個System.Core DLL的參考?沒有這個引用,.ToList()擴展方法將不可用。

此外,正如Workshop Alex指出的那樣,您的.ToList()調用位置不正確。

+0

其不支持ToList()的EF轉換器,引用是正確的 – AndreasN 2009-09-21 10:20:44

2
return (from t in Db.Transaction.Include("Lines") 
     select new bo.Transaction { 
     Id = t.Id, 
     Lines = t.Lines.OrderBy(l => l.RowNo), 
     }).ToList(); 

LINQ查詢只是不支持列表中,所以我們執行這個在枚舉結果。儘管如此,它確實會強制查詢執行正確。返回IEnumerable會延遲查詢的執行時間。 (基本上直到你要訪問數據的那一刻。)

+1

「Include」在這裏完全沒有必要。因爲你在投影,因此LINQ to Entities會爲你排序。否則正確(+1) – 2009-09-21 13:46:25

0

寫作Workshop Alex是正確的,但讓我解釋它背後的理論:
正如你可能知道的那樣,當你編寫一個LINQ-to -Entities查詢,你正在寫一些將針對你的數據庫執行的東西。爲了以一種有效的方式完成這項工作,我們不需要獲取每個實體,按照給定的條件對其進行測試,對結果進行排序和這些操作,查詢將被轉換爲SQL並針對您的數據庫運行。
但是,事實上,您的查詢接受任何有效的C#,並不意味着您可以編寫的所有代碼都具有對SQL的轉換。沒有翻譯的代碼的顯着例子是一個混合數據訪問和反射的實體類的查詢,或者 - 就像你的情況一樣 - 使用特殊的.NET數據類型的代碼。這種查詢通常可以分兩步進行,一個針對數據庫,另一個針對RAM中的實體。雖然這可能不會像你想要的那樣高效和乾淨,但因爲我個人不喜歡存儲過程,所以我仍然發現它比其他大多數方法好得多,只要你的約束允許你做出選擇。

編輯:
方案的確可以很容易地處理這種方式運行的數據庫查詢,並在內存部分的一部分:

 

Db.Transaction.Include("Lines").Select(t => new bo.Transaction { t.Id, Lines = t.Lines.OrderBy(l => l.RowNo) }).AsEnumerable().Select(t => new bo.Transacton { t.Id, Lines = t.Lines.ToList()}); 
 

的AsEnumerable呼叫有助於確保第二選擇是針對已從數據庫中獲取的一組對象運行的,因此不再存在將ToList轉換爲SQL的問題。

+0

我很清楚linq查詢的執行方式和時間。這不是問題在這裏。 問題是我無法將子查詢投影到其他對象的列表中。 它看起來比起在內存中執行部分查詢更傾向於拋出運行時異常。 – AndreasN 2009-09-21 12:14:31

+0

這實際上是關於翻譯和堆棧的哪一部分運行查詢,因爲您的問題實際上是您無法從LINQ查詢中急切地獲取集合,這是因爲SQL實際上沒有可調整大小的數組的線索。當然,你得到的異常並不是很清楚,但你必須考慮從你的查詢生成的SQL不會在你的dbms的其他地方運行或驗證,所以如果由於表達式生成了錯誤的SQL沒有翻譯,這是你將要得到的例外。 – em70 2009-09-21 13:33:10