2011-06-17 86 views
6

我想從下面的方法使用EntityFramework和Linq獲得總記錄數。返回計數很慢。Linq選擇語句慢時得到COUNT

public static int totalTracking(int id) 
{ 
    using (var ctx = new GPEntities()) 
    { 
     var tr = ctx.Tracking 
        .Where(c => c.clientID == Config.ClientID) 
        .Where(c => c.custID == id) 
        .Where(c => c.oOrderNum.HasValue) 
        .ToList(); 
     return tr.Count(); 
    }   
} 
+1

繼承人一個辦法,加快步伐,將查詢合併爲一個。我剛剛讀了一篇關於這個的文章。 http://msmvps.com/blogs/jon_skeet/archive/2011/06/16/linq-to-objects-and-the-performance-of-nested-quot-where-quot-calls.aspx?utm_source=feedburner&utm_medium = feed&utm_campaign = Feed%3A + JonSkeetCodingBlog +%28Jon + Skeet%27s +編碼+博客%29 – m4tt1mus 2011-06-17 00:08:04

回答

10

可以顯著簡化查詢:

using (var ctx = new GPEntities()) 
{ 
    return ctx.Tracking 
     .Where(c => c.clientID == Config.ClientID) 
     .Where(c => c.custID == id) 
     .Where(c => c.oOrderNum.HasValue) 
     .Count(); 
} 

當你調用ToList這將觸發物化,所以查詢將被髮布到數據庫和所有列將被檢索。實際的計數會發生在客戶端。

如果你只是Count,沒有ToList它會發出查詢,當你打電話Count和服務器將返回一個數字,而不是一個表。

這不是性能這個關鍵,但我認爲代碼看起來有點不漂亮,很多Where

using (var ctx = new GPEntities()) 
{ 
    return ctx.Tracking 
     .Where(c => 
      c.clientID == Config.ClientID && 
      c.custID == id && 
      c.oOrderNum.HasValue) 
     .Count(); 
} 

甚至

using (var ctx = new GPEntities()) 
{ 
    return ctx.Tracking 
     .Count(c => 
      c.clientID == Config.ClientID && 
      c.custID == id && 
      c.oOrderNum.HasValue); 
} 
+0

Man - 我剛纔看到.ToList() - 謝謝!您的代碼正在工作 – 2011-06-17 00:11:21

+0

我想通過討論它沒有什麼見解,但我更喜歡在Where-lambdas中不使用複合AND表達式。我發現當你可以做一個shift + del或添加一個新行時,它可以更容易地添加/刪除條件,並且它可以更容易地區分未實現的謂詞。 – kai 2016-02-21 17:32:42

2

刪除通話.ToList()。它強制查詢將整個結果拖到客戶端。

通過直接在TR(不ToList())的結果中移除此,和只調用.Count之間()時,Count()變得查詢本身的一部分,並且遠程地執行,這將大大簡化此:

public static int totalTracking(int id) 
{ 
    using (var ctx = new GPEntities()) 
    { 
     var tr = ctx.Tracking 
      .Where(c => c.clientID == Config.ClientID) 
      .Where(c => c.custID == id) 
      .Where(c => c.oOrderNum.HasValue); 

     // This can be added above, or left here - the end result is the same 
     return tr.Count(); 
    }   
} 
3

您可以非常簡化的東西,只是使用Count Extension method

你試過:

public static int totalTracking(int id) 
{ 
    using (var ctx = new GPEntities()) 
    { 
     return ctx.Tracking.Count(
        c => c.clientID == Config.ClientID && 
         c.custID == id && 
         c.oOrderNum.HasValue); 
    }   
} 
+0

順便說一句 - 錯誤的擴展方法鏈接 - 嘗試http://msdn.microsoft.com/en-us/library/bb534807.aspx,而不是... – 2011-06-17 00:12:36

+0

@Reed Copsey thxs,如果微軟將停止搞亂他們的文檔,它會做回答StackOverflow問題非常容易:) – Nix 2011-06-17 00:13:52

+0

@Nik:沒問題 - 你用的是IEnumerable,而不是IQueryable;) – 2011-06-17 00:18:53