Beg*_*ner 7 .net c# linq performance entity-framework
我目前有一个查询,由于数据库中的数据量不会花费很长时间,有时会崩溃.
有人可以注意到我能做些什么来帮助加快速度吗?
public IList<Report> GetReport(CmsEntities context, long manufacturerId, long? regionId, long? vehicleTypeId)
{
var now = DateTime.Now;
var today = new DateTime(now.Year, now.Month, 1);
var date1monthago = today.AddMonths(-1);
var date2monthago = today.AddMonths(-2);
var date3monthago = today.AddMonths(-3);
var date4monthago = today.AddMonths(-4);
var date5monthago = today.AddMonths(-5);
var date6monthago = today.AddMonths(-6);
today = TimeManager.EndOfDay(new DateTime(now.AddMonths(-1).Year, today.AddMonths(-1).Month, DateTime.DaysInMonth(now.Year, today.AddMonths(-1).Month)));
var query = from item in context.Invoices
where item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Select(x => x.ManufacturerId).Contains(manufacturerId)
&& (item.InvoiceDate >= date6monthago && item.InvoiceDate <= today)
&& (regionId.HasValue && regionId.Value > 0 ? item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Select(x => x.RegionId).Contains(regionId.Value) : true)
&& (item.InvType == "I" || item.InvType == null)
&& (vehicleTypeId.HasValue && vehicleTypeId.Value > 0 ? item.Repair.Job.Vehicle.Model.VehicleTypes.Select(x => x.Id).Contains(vehicleTypeId.Value) : true)
select item;
var query2 = from item in query
group item by new { item.Repair.Job.Bodyshop } into g
let manufJobs = query.Where(x => x.Repair.Job.Vehicle.Model.ManufacturerId == manufacturerId && x.Repair.Job.BodyshopId == g.Key.Bodyshop.Id)
let allJobs = query.Where(x => x.Repair.Job.BodyshopId == g.Key.Bodyshop.Id)
select new tReport
{
MonthSixManufJobTotal = manufJobs.Where(x => x.InvoiceDate.Month == date6monthago.Month && x.InvoiceDate.Year == date6monthago.Year).GroupBy(x => x.Repair.Job).Count(),
MonthSixJobTotal = allJobs.Where(x => x.InvoiceDate.Month == date6monthago.Month && x.InvoiceDate.Year == date6monthago.Year).GroupBy(x => x.Repair.Job).Count(),
MonthFiveManufJobTotal = manufJobs.Where(x => x.InvoiceDate.Month == date5monthago.Month && x.InvoiceDate.Year == date5monthago.Year).GroupBy(x => x.Repair.Job).Count(),
MonthFiveJobTotal = allJobs.Where(x => x.InvoiceDate.Month == date5monthago.Month && x.InvoiceDate.Year == date5monthago.Year).GroupBy(x => x.Repair.Job).Count(),
MonthFourManufJobTotal = manufJobs.Where(x => x.InvoiceDate.Month == date4monthago.Month && x.InvoiceDate.Year == date4monthago.Year).GroupBy(x => x.Repair.Job).Count(),
MonthFourJobTotal = allJobs.Where(x => x.InvoiceDate.Month == date4monthago.Month && x.InvoiceDate.Year == date4monthago.Year).GroupBy(x => x.Repair.Job).Count(),
MonthThreeManufJobTotal = manufJobs.Where(x => x.InvoiceDate.Month == date3monthago.Month && x.InvoiceDate.Year == date3monthago.Year).GroupBy(x => x.Repair.Job).Count(),
MonthThreeJobTotal = allJobs.Where(x => x.InvoiceDate.Month == date3monthago.Month && x.InvoiceDate.Year == date3monthago.Year).GroupBy(x => x.Repair.Job).Count(),
MonthTwoManufJobTotal = manufJobs.Where(x => x.InvoiceDate.Month == date2monthago.Month && x.InvoiceDate.Year == date2monthago.Year).GroupBy(x => x.Repair.Job).Count(),
MonthTwoJobTotal = allJobs.Where(x => x.InvoiceDate.Month == date2monthago.Month && x.InvoiceDate.Year == date2monthago.Year).GroupBy(x => x.Repair.Job).Count(),
MonthOneManufJobTotal = manufJobs.Where(x => x.InvoiceDate.Month == date1monthago.Month && x.InvoiceDate.Year == date1monthago.Year).GroupBy(x => x.Repair.Job).Count(),
MonthOneJobTotal = allJobs.Where(x => x.InvoiceDate.Month == date1monthago.Month && x.InvoiceDate.Year == date1monthago.Year).GroupBy(x => x.Repair.Job).Count(),
ManufTotal = manufJobs.GroupBy(x => x.Repair.Job).Count(),
Total = allJobs.GroupBy(x => x.Repair.Job).Count(),
PercentageOf = ((decimal)manufJobs.GroupBy(x => x.Repair.Job).Count() / (decimal)allJobs.GroupBy(x => x.Repair.Job).Count()) * 100
};
return query2.OrderBy(x => x).ToList();
}
Run Code Online (Sandbox Code Playgroud)
编辑
var query = from item in context.Invoices.AsNoTracking()
where item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Any(x => x.ManufacturerId == manufacturerId)
&& (item.InvoiceDate >= date12monthago && item.InvoiceDate <= today)
&& (item.InvType == "I" || item.InvType == null)
select item;
if (regionId.HasValue && regionId.Value > 0)
{
query = query.Where(item => item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Select(x => x.RegionId).Contains(regionId.Value));
}
if (vehicleTypeId.HasValue && vehicleTypeId.Value > 0)
{
query = query.Where(item => item.Repair.Job.Vehicle.Model.VehicleTypes.Select(x => x.Id).Contains(vehicleTypeId.Value));
}
var query2 = from item in hey
group item by new { item.Repair.Job.Bodyshop, item.InvoiceDate.Month } into m
select new TReport
{
Bodyshop = m.Key.Bodyshop.Name,
Bays = m.Key.Bodyshop.Bays,
Region = m.Key.Bodyshop.Manufacturer2Bodyshop.FirstOrDefault(x => x.ManufacturerId == manufacturerId).Region.Name,
BodyshopCode = m.Key.Bodyshop.Manufacturer2Bodyshop.FirstOrDefault(x => x.ManufacturerId == manufacturerId).BodyshopCode,
Total = m.Count(),
ManufTotal = m.Where(x => x.Repair.Job.Vehicle.Model.ManufacturerId == manufacturerId).Count(),
Totals = m.GroupBy(j => j.InvoiceDate.Month).Select(j => new TPercentReportInner
{
Month = j.Key,
ManufTotal = j.Where(x => x.Repair.Job.Vehicle.Model.ManufacturerId == manufacturerId).Count(),
AllTotal = j.Count()
})
};
Run Code Online (Sandbox Code Playgroud)
我切断了查询.但即使现在表现比以前更差?
我首先从查询中删除硬编码的可选条件,这将允许查询优化器根据您拥有的参数使用不同的查询计划,例如:
var query = from item in context.Invoices.AsNoTracking()
where item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Select(x => x.ManufacturerId).Contains(manufacturerId)
&& (item.InvoiceDate >= date12monthago && item.InvoiceDate <= today)
&& (item.InvType == "I" || item.InvType == null)
select item;
if (regionId.HasValue && regionId.Value > 0)
query=query.Where(item=>item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Select(x => x.RegionId).Contains(regionId.Value));
if (vehicleTypeId.HasValue && vehicleTypeId.Value > 0)
query=query.Where(item=>item.Repair.Job.Vehicle.Model.VehicleTypes.Select(x => x.Id).Contains(vehicleTypeId.Value));
var query2 = from item in query
group item by new { item.InvoiceDate.Month, item.Repair.Job.Bodyshop } into g
select new TReport
{
BodyshopId = g.Key.Bodyshop.Id,
Month = g.Key.Month,
MonthAllJobTotal = g.Count()
};
return query2.ToList();
Run Code Online (Sandbox Code Playgroud)
您还可以检查是否转换.Select(x=>x.id).Contains(id)或.Any(x=>x.Id==id)执行速度更快,尽管我认为它们在查询计划和执行速度方面会相似.那会给你:
var query = from item in context.Invoices.AsNoTracking()
where item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Any(m=>m.ManufacturerId==manufacturerId)
&& (item.InvoiceDate >= date12monthago && item.InvoiceDate <= today)
&& (item.InvType == "I" || item.InvType == null)
select item;
if (regionId.HasValue && regionId.Value > 0)
query=query.Where(item=>item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Any(m=>m.RegionId==regionId.Value));
if (vehicleTypeId.HasValue && vehicleTypeId.Value > 0)
query=query.Where(item=>item.Repair.Job.Vehicle.Model.VehicleTypes.Any(v=>v.Id==vehicleTypeId.Value));
var query2 = from item in query
group item by new { item.InvoiceDate.Month, item.Repair.Job.Bodyshop } into g
select new TReport
{
BodyshopId = g.Key.Bodyshop.Id,
Month = g.Key.Month,
MonthAllJobTotal = g.Count()
};
return query2.ToList();
Run Code Online (Sandbox Code Playgroud)
根据你所拥有的,我猜你会.AsNoTracking()为你做的很少,但它不会受到伤害.它在检索大量实体时会产生更大的影响,而这似乎并没有发生.
然后,我会通过删除硬编码的ManufacturerId来清理和标准化您的查询,这将为您提供:
var query = from item in context.Invoices.AsNoTracking()
where (item.InvoiceDate >= date12monthago && item.InvoiceDate <= today)
&& (item.InvType == "I" || item.InvType == null)
select item;
if (manufacturerId.HasValue && manufacturerId.Value > 0)
query=query.Where(item=>item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Any(m=>m.ManufacturerId==manufacturerId));
if (regionId.HasValue && regionId.Value > 0)
query=query.Where(item=>item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Any(m=>m.RegionId==regionId.Value));
if (vehicleTypeId.HasValue && vehicleTypeId.Value > 0)
query=query.Where(item=>item.Repair.Job.Vehicle.Model.VehicleTypes.Any(v=>v.Id==vehicleTypeId.Value));
var query2 = from item in query
group item by new { item.InvoiceDate.Month, item.Repair.Job.Bodyshop } into g
select new TReport
{
BodyshopId = g.Key.Bodyshop.Id,
Month = g.Key.Month,
MonthAllJobTotal = g.Count()
};
return query2.ToList();
Run Code Online (Sandbox Code Playgroud)
然后,我会返回一个IQueryable而不是List,这样如果你不需要一个或多个列,它们可以从最终查询中删除,如:
public IQueryable<Report> GetReport(CmsEntities context, long? manufacturerId, long? regionId, long? vehicleTypeId)
{
{
var now = DateTime.Now;
var today = new DateTime(now.Year, now.Month, 1);
var date1monthago = today.AddMonths(-1);
var date2monthago = today.AddMonths(-2);
var date3monthago = today.AddMonths(-3);
var date4monthago = today.AddMonths(-4);
var date5monthago = today.AddMonths(-5);
var date6monthago = today.AddMonths(-6);
today = TimeManager.EndOfDay(new DateTime(now.AddMonths(-1).Year, today.AddMonths(-1).Month, DateTime.DaysInMonth(now.Year, today.AddMonths(-1).Month)));
var query = from item in context.Invoices.AsNoTracking()
where (item.InvoiceDate >= date12monthago && item.InvoiceDate <= today)
&& (item.InvType == "I" || item.InvType == null)
select item;
if (manufacturerId.HasValue && manufacturerId.Value > 0)
query=query.Where(item=>item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Any(m=>m.ManufacturerId==manufacturerId));
if (regionId.HasValue && regionId.Value > 0)
query=query.Where(item=>item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Any(m=>m.RegionId==regionId.Value));
if (vehicleTypeId.HasValue && vehicleTypeId.Value > 0)
query=query.Where(item=>item.Repair.Job.Vehicle.Model.VehicleTypes.Any(v=>v.Id==vehicleTypeId.Value));
var query2 = from item in query
group item by new { item.InvoiceDate.Month, item.Repair.Job.Bodyshop } into g
select new TReport
{
BodyshopId = g.Key.Bodyshop.Id,
Month = g.Key.Month,
MonthAllJobTotal = g.Count()
};
return query2;
}
Run Code Online (Sandbox Code Playgroud)
然后我将这些分开并将这些转换为扩展方法:
public static class MyExtensions
{
public static IQueryable<Invoice> Recent(this IQueryable<Invoice> context,long? manufacturerId=null,long? regionId=null,long? vehicleId=null)
{
var now = DateTime.Now;
var today = new DateTime(now.Year, now.Month, 1);
var date1monthago = today.AddMonths(-1);
var date2monthago = today.AddMonths(-2);
var date3monthago = today.AddMonths(-3);
var date4monthago = today.AddMonths(-4);
var date5monthago = today.AddMonths(-5);
var date6monthago = today.AddMonths(-6);
today = TimeManager.EndOfDay(new DateTime(now.AddMonths(-1).Year, today.AddMonths(-1).Month, DateTime.DaysInMonth(now.Year, today.AddMonths(-1).Month)));
var query = from item in context.Invoices.AsNoTracking()
where (item.InvoiceDate >= date12monthago && item.InvoiceDate <= today)
&& (item.InvType == "I" || item.InvType == null)
select item;
if (manufacturerId.HasValue && manufacturerId.Value > 0)
query=query.Where(item=>item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Any(m=>m.ManufacturerId==manufacturerId));
if (regionId.HasValue && regionId.Value > 0)
query=query.Where(item=>item.Repair.Job.Bodyshop.Manufacturer2Bodyshop.Any(m=>m.RegionId==regionId.Value));
if (vehicleTypeId.HasValue && vehicleTypeId.Value > 0)
query=query.Where(item=>item.Repair.Job.Vehicle.Model.VehicleTypes.Any(v=>v.Id==vehicleTypeId.Value));
return query;
}
public static IQueryable<Report> ToReport(this IQueryable<Invoice> context)
{
return (from item in query
group item by new { item.InvoiceDate.Month, item.Repair.Job.Bodyshop } into g
select new TReport
{
BodyshopId = g.Key.Bodyshop.Id,
Month = g.Key.Month,
MonthAllJobTotal = g.Count()
});
}
}
Run Code Online (Sandbox Code Playgroud)
现在您可以执行以下操作:
var reports=db.Invoices.Recent.ToReport();
Run Code Online (Sandbox Code Playgroud)
要么
var reports=db.Invoices.Recent(ManufacturerEnum.Toyota).ToReport();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
487 次 |
| 最近记录: |