此查询是在我们的系统中编写的,但是这个查询的性能越来越差,数据略有增加。我的调查显示(CodeCount
)其中查询触发另一个子查询导致执行大量延迟。我需要优化这个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
});
答案 0 :(得分:1)
第一个大问题是ObjectSet前面的ToList()
权限<> (EF中的表格集合)。
永远不要这样做,ToList()
强制EF在处理查询之前将所有数据带入内存。 (就像@Daniel Hilgarth一样)。
其他细节是使用FirstOrDefault()
前面的get属性,如行:
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。但我相信这种改善会表现得更好。