2013-03-06 110 views
3

我試圖通過實體數據模型從大約2000萬條目的MS SQL數據庫中的表中提取每條記錄。我最初的想法是檢索塊中的數據,就像這樣:使用LINQ處理大型SQL查詢

public IEnumerable<IEnumerable<device>> GetDevicesInChunks(int chunkSize) 
{ 
    using (var db = new AccountsEntities()) 
    { 
     for (int i = 0; i < db.devices.Count(); i += chunkSize) 
     { 
      yield return db.devices.Skip(i).Take(chunkSize); 
     } 
    } 
} 

然而,看來我必須調用OrderBy我叫Skip之前,由當我採用上述方法時拋出的異常判斷

The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 
'OrderBy' must be called before the method 'Skip'. 

對於我檢索的每個記錄子集,我確定致電OrderBy將是昂貴的,因爲設備沒有特定的順序 - 我覺得我在這裏走錯了路。

通過LINQ處理大型SQL查詢的最佳方法是什麼?

+0

你不能使用'Where'並用主鍵而不是'Skip'來過濾嗎?或者只是'OrderBy'的主鍵? – 2013-03-06 23:53:15

+0

有什麼特別的原因讓你必須以大塊的方式做到這一點? – Tory 2013-03-06 23:56:55

+2

@Tory我認爲一次加載2000萬個實體會是足夠的理由。 – 2013-03-07 00:04:57

回答

2

發生錯誤是因爲方法Skip需要在OrderBy之後運行。如果沒有OrderBy,您將無法運行跳過。方法Skip需要知道要採取的第一個方法,並且如果您將第一個需要知道選擇的順序的信息知道第一個是從開始到結束還是從開始到結束。

你可以閱讀更多here

所以,你的代碼看起來是這樣的:

public IEnumerable<IEnumerable<device>> GetDevicesInChunks(int chunkSize) 
{ 
    using (var db = new AccountsEntities()) 
    { 
     for (int i = 0; i < db.devices.Count(); i += chunkSize) 
     { 
      yield return db.devices.OrderByDescending(y => y).Skip(i).Take(chunkSize); 
     } 
    } 
} 

,如果你認爲這是一個沉重的查詢,remeber實體框架可以做緩存查詢和數據的。如果你不喜歡這種方法的SQL,你可以run the query manually

個人經驗: 我用一個數據庫與2 bi行和...它不是很慢。但是我在表格中有索引,我總是使用緩存。

欲瞭解更多: 如果您願意,您可以使用程序。查看更多here

+0

非常全面的答案,感謝所有的信息和解釋!爲了確保正確理解,OrderByDescending表達式應該是y => y.id而不是y => y,對嗎? – 2013-03-07 01:10:41

+0

ops,也許可以是 – MayogaX 2013-03-07 02:02:26

0

您可能不需要做OrderBy - 您只需在做SkipTake之前填寫清單即可。我認爲您可以使用.Count()來填充查詢,之後您可以使用SkipTake

+0

這將是非常沉重的,使用Count或ToList如你所說將填充查詢,但將檢索2000萬條記錄。 – 2013-03-07 00:33:30

+0

確實...但它不會將整個集合從服務器中推出來進行計數 - 它會將其填充到MSSQL中。 – 2013-03-07 00:37:47