2012-05-09 67 views
1

我有一個場景導致運行很長的進程,並懷疑它是我們使用LINQ to Entity。要LINQ或不LINQ:關於LINQ到實體/ SQL /對象

背景: 項目正在使用LINQ To Entity和Repository模式將數據公開給我們的邏輯層。這是如何,不會改變。

ISSUE: 某種情況已經出現,需要從輸入和其他表中選擇相交的數據。爲了優化這個,我首先向數據庫查詢了一個我打算用於獲取相交數據的ID數組。我還有另一個用於我的LINQ表達式的整數數組。然後,我建立一個表達式,從LINQ中的表中選擇數據並在其中包含方法。這需要很長時間才能執行。幾乎一分鐘。

爲了對抗這一點,我嘗試了幾乎所有幾乎相同時間的LINQ技術。爲了提供信息,下面是我的一些方法的示例。

// FYI: tableTotalsIds contains 14,856 IDs as an example, built from a repository call 
var tableTotalsIds = tableTotals.Select(s => s.Id).ToArray(); 
int[] ages = {25, 26, 27}; 

Expression<Func<TotalAgeCounts, bool>> ageFilter = 
    af => af.TableTotalsId != null && 
      tableTotalsIds.Contains(af.TableTotalsId.Value) && 
      ages.Contains(af.Age); 

var directStartTime = DateTime.Now; 
var directFetch = _ctx.TotalAgeCounts.Where(ageFilter).ToList(); 
var directBenchMark = DateTime.Now.Subtract(directStartTime).TotalSeconds; 

var repositoryStartTime = DateTime.Now; 
var repositoryFetch = _totalAgeCountsRepository 
    .SelectAll(new Specification<TotalAgeCounts>(ageFilter)); 
var repositoryBenchMark = DateTime.Now.Subtract(repositoryStartTime).TotalSeconds; 

在所有情況下,查詢時間大約需要1分鐘。跳到我身上的是在.Contains()方法中使用的大量tableTotalsIds,但我不知道其他LINQ方法來實現此目的。

在LINQ中有更好的方法嗎?

目前我正在考慮將此查詢作爲簡單連接放回數據庫中,並跳過此處的LINQ瓶頸。但首先我會嘗試將未過濾的數據拉入內存,然後使用LINQ將數據連接在一起,看看會有多高效。

我對其他人如何克服類似瓶頸而不重寫應用程序的體系結構感興趣。

SOLUTION

正如批評家指出,LINQ優化沒有發生由於我.ToArray()。問題變得更深了,因爲我正在使用我們的Repository實現來構建tableTotalsIds,該tableTotalsIds已經將結果投給了IList,從而失去了進一步的LINQ/SQL優化。只需不使用我們的Repository實現來構建tableTotalsIds並直接查詢dataContext,將結果留作IQueryable即可解決問題。

+1

您是否首先從數據庫中獲取總ID?你需要將它們拉回來,然後將它們反饋回LINQ,或者你可以在數據庫上做所有的事情嗎?如果在tableTotalsId上放置'ToArray',會發生什麼? – Rup

+0

@rup完全是我的第一個想法。「優化」似乎是這個問題的重要組成部分。在這裏運行的查詢沒有什麼複雜的。 –

+0

目前,這些ID是從數據庫中提取的(這似乎是浪費時間)。 ToArray在那裏阻止它重新查詢,所以我認爲它應該使其更快,如果有的話。獲取ID不需要很長時間,其後面的查詢就可以完成。 – Arkiliknam

回答

4

您調用ToArray這一事實會導致過濾記錄從數據庫中提取出來,只能作爲查詢的一部分再次注入。這可以防止查詢優化器充分利用它已經擁有它所需的事實。正如你在紀念中注意到的那樣,刪除Tolist/toarray是有幫助的。

至於存儲庫模式,沒有理由不能使用它。你不需要爲每個班級單獨存儲庫;只針對那些重要的,你會查詢的根對象。

在這種情況下,您的幫助表信息可以在同一查詢中彙總;存儲庫模式不要求您爲其創建一個sepatate存儲庫。

+0

感謝您的解釋。我收回了我所說的關於刪除Repository的用法,並同意在這種情況下它不是必需的。我不知道IQueryable可以優化更多的數據庫調用。學習到教訓了! – Arkiliknam