2013-06-04 143 views
1

這種查詢是寫在我們的系統中,前一段時間,但此查詢的表現越來越差,在數據略有增加。我的調查顯示(CodeCount)查詢觸發另一個子查詢導致執行大量延遲。我需要優化這個Linq查詢。任何幫助將不勝感激子查詢和集團在LINQ

from batch in Context.VoucherCodeBatch.ToList() 
        join type in Context.VoucherCodeType on batch.VoucherTypeId equals type.VoucherTypeId 
        join voucher in Context.Voucher on batch.VoucherCodeBatchId equals voucher.VoucherCodeBatchId 

        where batchIds.Contains(batch.BatchCode) 
        group new 
        { 
         batch.BatchCode, 
         batch.CreationDate, 
         type.VoucherTypeName, 
         voucher.AllowedCount, 
         voucher.ValidFrom, 
         voucher.ValidTo, 
         batch.VoucherCodeBatchId, 
         voucher.VoucherCode 
        } 
         by new { batch.BatchCode } 
         into uniquebatch 
         select new Batch 
         { 
          BatchCode = uniquebatch.FirstOrDefault().BatchCode, 
          CreationDate = uniquebatch.FirstOrDefault().CreationDate, 
          TimesAllowed = uniquebatch.FirstOrDefault().AllowedCount, 
          ValidFrom = uniquebatch.FirstOrDefault().ValidFrom, 
          CodeCount = ((from c in Context.Voucher.ToList() 
              where 
               c.VoucherCodeBatchId == 
               uniquebatch.FirstOrDefault().VoucherCodeBatchId 
              select c).Count()), 
          ValidTo = uniquebatch.FirstOrDefault().ValidTo, 
          CodeType = uniquebatch.FirstOrDefault().VoucherTypeName, 
          VoucherCodeBatchId = uniquebatch.FirstOrDefault().VoucherCodeBatchId 
         }); 
+3

那'ToList()'在那裏意味着這個查詢請求* *所有從內存中的數據庫和過濾器券行。嘗試刪除它。 –

+0

我建議在數據庫端執行SQL查詢。 –

+0

我同意Ewald。甚至可以將它製作成一個視圖,然後您可以在LINQ中更輕鬆地進行選擇。很多時候,僅僅因爲你可以在LINQ中完成它並不意味着它是最好的方法。 –

回答

1

第一個大問題是ToList()權的對象集<前>(表收集EF)。

決不做,ToList()力EF把所有的數據存儲過程之前查詢。 (就像@Daniel Hilgarth評論)。

其他細節是符合使用的FirstOrDefault()前面獲取屬性,如:在這種情況下

BatchCode = uniquebatch.FirstOrDefault().BatchCode, 

使用First()代替FirstOrDefault。像:

BatchCode = uniquebatch.First().BatchCode, 

您的查詢將是這樣的:

from batch in Context.VoucherCodeBatch/*.ToList()*/ 
join type in Context.VoucherCodeType on batch.VoucherTypeId equals type.VoucherTypeId 
join voucher in Context.Voucher on batch.VoucherCodeBatchId equals voucher.VoucherCodeBatchId 
where batchIds.Contains(batch.BatchCode) 
group new 
    { 
     batch.BatchCode, 
     batch.CreationDate, 
     type.VoucherTypeName, 
     voucher.AllowedCount, 
     voucher.ValidFrom, 
     voucher.ValidTo, 
     batch.VoucherCodeBatchId, 
     voucher.VoucherCode 
    } 
by new { batch.BatchCode } 
into uniquebatch 
select (delegate 
    { 
     // If you put a operation in a query that operation will be 
     // processed all times. Bacause that i removed this line from 
     // the where statement. 
     var vcBatchId = uniquebatch.First().VoucherCodeBatchId; 

     return new Batch 
      { 
       BatchCode = uniquebatch.First().BatchCode, 
       CreationDate = uniquebatch.First().CreationDate, 
       TimesAllowed = uniquebatch.First().AllowedCount, 
       ValidFrom = uniquebatch.First().ValidFrom, 
       CodeCount = ((
        from c in Context.Voucher/*.ToList()*/ 
        where c.VoucherCodeBatchId == vcBatchId 
        select c).Count()), 
       ValidTo = uniquebatch.First().ValidTo, 
       CodeType = uniquebatch.First().VoucherTypeName, 
       VoucherCodeBatchId = uniquebatch.First().VoucherCodeBatchId 
      } 
    }); 

如果這種改進是不夠好,你需要改變這個查詢SQL。但我相信這種改善會更好。

+0

感謝您關注此事。代表意味着什麼。我完全複製了上面的代碼,並且編譯器抱怨select(select)子句中的select(delegate)表達式的類型是不正確的。類型推斷在調用'Select'時失敗 – user1071222