2013-06-04 63 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