我的实体结构如下:
public class DisbursementItem { public int DisbursementNumber; public int IDDisbursementItem; public int IDReceiptItem; public decimal Amount; public decimal MeasureUnit; public decimal PricePerMU; public decimal PriceTotal; public Disbursement Disbursement_IDDisbursement; public int IDDisbursementNumber; } public class Disbursement { public int DisbursementNumber; DateTime date; DisbursementType DType; string Note; string Subscriber; Subscriber SubscriberModel; string ItemType; int ProcessNumber; } public class Subscriber { public string Name public string Address; public string City; } public class DisbursementDescription { public int IDDisbursementItem; public string Description; } public class Receipt { public int IDReceiptItem; public int ItemNumber; } public class StorageCard { public int ItemNumber; public string StorageCardGroup; public string StorageCardName; }
我的 EF6 LINQ 查询是:
DateTime from; DateTime to; var result = context.DisbursementItem .Where(x => x.Disbursement_IDDisbursement.Date <= to && x.Disbursement_IDDisbursement.Date >= from) .Join(context.DisbursementDescription, di => di.IDDisbursementItem, dd => dd.IDDisbursementItem, (di, dd) => new {di = di, desc = dd.Description}) .Join(context.Receipt, x => x.di.IDReceiptItem, r => r.IDReceiptItem, (x, r) => new { di = x.di, desc = x.desc, r = r }) .Join(context.StorageCard, x => x.r.ItemNumber, sc => sc.ItemNumber, (x, sc) => new { di = x.di, desc = x.desc, r = x.r, sc = sc}) .GroupBy(g => new {g.di.DisbursementNumber, g.sc.ItemNumber, g.di.MeasureUnit}) .Select(x => new { Date = x.FirstOrDefault().di.Disbursement_IDDisbursement.Date, DisbursementNumber = x.Key.DisbursementNumber, DType = x.FirstOrDefault().di.Disbursement_IDDisbursement.DType, Note = x.FirstOrDefault().di.Disbursement_IDDisbursement.Note, Subscriber = x.FirstOrDefault().di.Disbursement_IDDisbursement.Subscriber, SubscriberName = x.FirstOrDefault().di.Disbursement_IDDisbursement.SubscriberModel.Name, SubscriberAddress = x.FirstOrDefault().di.Disbursement_IDDisbursement.SubscriberModel.Address, SubscriberCity = x.FirstOrDefault().di.Disbursement_IDDisbursement.SubscriberModel.City, ItemNumber = x.FirstOrDefault().sc.ItemNumber, StorageCardGroup = x.FirstOrDefault().sc.StorageCardGroup, StorageCardName = x.FirstOrDefault().sc.StorageCardName, Amount = x.Sum(y => y.di.Amount), PricePerMU = x.FirstOrDefault().di.PricePerMU, PriceTotal = x.Sum(y => y.di.PriceTotal), MeasureUnit = x.Key.MeasureUnit Desc = x.FirstOrDefault().desc, }) SELECT di.Date, di.DisbursementNumber, d.DType, d.Note, d.Subscriber, subs.Name, subs.Address, subs.City, sc.ItemNumber, sc.StorageCardGroup, sc.StorageCardName, Sum(di.Amount) as Amount, di.PricePerMU, Sum(di.PriceTotal) as PriceTotal, di.MeasureUnit, dd.Description FROM DisbursementItem as di INNER JOIN Disbursement as d ON di.IDDisbursementNumber = d.DisbursementNumber INNER JOIN Receipt as r ON di.IDReceiptItem = r.IDReceiptItem INNER JOIN StorageCard as sc ON r.ItemNumber = sc.ItemNumber INNER JOIN DisbursementDescription dd ON di.IDDisbuzrsementItem = dd.IDDisbursementItem WHERE di.Date <= ... and di.Date >= ... GROUP BY di.DisbursementNumber, sc.ItemNumber, di.MeasureUnit
这就是我想在 EF 中实现的 SQL 查询
对于几百行,此查询可能需要一分钟多的时间。我该如何优化它?我怀疑多重连接是一个问题,也许也是Sum某些领域的问题。
Sum
也不能修改数据库模式。
它产生的查询是巨大的。这就像 SELECT in SELECT in SELECT 一样 40 次。
最简单的方法是将结果所需的所有字段添加到分组键中。将查询重写为查询语法以提高可读性和可维护性:
DateTime from; DateTime to; var query = from di in context.DisbursementItem where di.Disbursement_IDDisbursement.Date <= to && di.Disbursement_IDDisbursement.Date >= from join dd in context.DisbursementDescription on di.IDDisbursementItem equals dd.IDDisbursementItem join r in context.Receipt on di.IDReceiptItem equals r.IDReceiptItem join sc in context.StorageCard on r.ItemNumber equals sc.ItemNumber group di by new { di.DisbursementNumber, sc.ItemNumber, di.MeasureUnit, di.Disbursement_IDDisbursement.Date, di.Disbursement_IDDisbursement.DType, di.Disbursement_IDDisbursement.Note, Subscriber = di.Disbursement_IDDisbursement.Subscriber, SubscriberName = di.Disbursement_IDDisbursement.SubscriberModel.Name, SubscriberAddress = di.Disbursement_IDDisbursement.SubscriberModel.Address, SubscriberCity = di.Disbursement_IDDisbursement.SubscriberModel.City, sc.ItemNumber, sc.StorageCardGroup, sc.StorageCardName, di.PricePerMU, Desc = dd.Description } into g select new { g.Key.Date, g.Key.DisbursementNumber, g.Key.DType, g.Key.Note, g.Key.Subscriber, g.Key.SubscriberName, g.Key.SubscriberAddress, g.Key.SubscriberCity, g.Key.ItemNumber, g.Key.StorageCardGroup, g.Key.StorageCardName, g.Key.PricePerMU, g.Key.MeasureUnit, g.Key.Desc, Amount = g.Sum(x => x.Amount), PriceTotal = g.Sum(x => x.PriceTotal) }