C# 加速linq组和查询
我有一个查询,它处理从各种表中提取的大约500条记录,将它们分组,然后汇总(如果是一个词的话)到一个工作报告中。一切正常,但运行这个报告大约需要30秒,我收到了用户的投诉 所讨论的程序如下:C# 加速linq组和查询,c#,asp.net,linq,entity-framework,C#,Asp.net,Linq,Entity Framework,我有一个查询,它处理从各种表中提取的大约500条记录,将它们分组,然后汇总(如果是一个词的话)到一个工作报告中。一切正常,但运行这个报告大约需要30秒,我收到了用户的投诉 所讨论的程序如下: public static List<LabourEfficiencies> GetLabourEfficienciesByTimeSheet(DateTime dateFrom, DateTime dateTo) { CS3Entities ctx = new
public static List<LabourEfficiencies> GetLabourEfficienciesByTimeSheet(DateTime dateFrom, DateTime dateTo)
{
CS3Entities ctx = new CS3Entities();
//get all relevant timesheetline items
var tsItems = from ti in ctx.TimeSheetItems
where ti.TimeSheetHeader.Date >= dateFrom && ti.TimeSheetHeader.Date <= dateTo && ti.TimeSheetHeader.TimeSheetCategory != "NON-PROD"
select new TimesheetLine
{
TimesheetNo = ti.TimeSheetNo,
HoursProduced = ti.HoursProduced,
HoursProducedNet = ti.HoursProducedNet,
ItemID = ti.ItemID,
ProcessID = ti.ProcessID,
ProcessDuration = ti.ProcessDuration,
DowntimeHours = 0M
};
//get all relevant downtimeline items
var tsDownT = from dt in ctx.DowntimeItems
where dt.TimeSheetHeader.Date >= dateFrom && dt.TimeSheetHeader.Date <= dateTo && dt.TimeSheetHeader.TimeSheetCategory != "NON-PROD"
select new TimesheetLine
{
TimesheetNo = dt.TimeSheetNo,
HoursProduced = 0M,
HoursProducedNet = 0M,
ItemID = "",
ProcessID = "",
ProcessDuration = 0M,
DowntimeHours = dt.DowntimeHours
};
//combine them into single table
var tsCombi = tsItems.Concat(tsDownT);
var flatQuery = (from c in tsCombi
join th in ctx.TimeSheetHeaders on c.TimesheetNo equals th.TimeSheetNo
select new
{
th.TimeSheetNo,
th.EmployeeNo,
th.TimeSheetCategory,
th.Date,
c.HoursProduced,
c.ProcessDuration,
th.HoursWorked,
c.HoursProducedNet,
c.DowntimeHours,
c.ItemID
});
//add employee details & group by timesheet no (1 line per timesheet no)
//NB. FnTlHrs checks whether there are any indirect hrs & deducts them if there are
var query = flatQuery.GroupBy(f => f.TimeSheetNo).Select(g => new LabourEfficiencies
{
Eno = g.FirstOrDefault().EmployeeNo,
Dept =g.FirstOrDefault().TimeSheetCategory,
Date = g.FirstOrDefault().Date,
FnGrHrs =g.Where(w =>w.TimeSheetCategory == "FN" &&!w.ItemID.StartsWith("090")).Sum(h => h.HoursProduced),
FnTlHrs =g.Where(w =>w.ItemID.StartsWith("090")).Sum(h => h.ProcessDuration) >0? (g.FirstOrDefault(w =>w.TimeSheetCategory =="FN").HoursWorked) -(g.Where(w =>w.ItemID.StartsWith("090")).Sum(h =>h.ProcessDuration)): g.FirstOrDefault(w =>w.TimeSheetCategory =="FN").HoursWorked,
RmGrHrs =g.Where(w =>w.TimeSheetCategory == "RM").Sum(h => h.HoursProduced),RmGrHrsNet =g.Where(w =>w.TimeSheetCategory == "RM").Sum(h => h.HoursProducedNet),
RmTlHrs =g.FirstOrDefault(w =>w.TimeSheetCategory == "RM").HoursWorked,
MpGrHrs =g.Where(w =>w.TimeSheetCategory =="MATPREP").Sum(h => h.HoursProduced),
MpTlHrs =g.FirstOrDefault(w =>w.TimeSheetCategory =="MATPREP").HoursWorked,
DtHrs = g.Sum(s => s.DowntimeHours),
Indirect =g.Where(w =>w.ItemID.StartsWith("090")).Sum(h => h.ProcessDuration)
});
return query.ToList();
}
公共静态列表GetLaboureficienciesByTimesheet(DateTime dateFrom,DateTime dateTo)
{
CS3Entities ctx=新的CS3Entities();
//获取所有相关的时间表项目
var tsItems=来自ctx.Timesheetims中的ti
其中ti.timesheetader.Date>=dateFrom&&ti.timesheetader.Date=dateFrom&&dt.timesheetader.Date f.TimeSheetNo)。选择(g=>new-laboureficiencies
{
Eno=g.FirstOrDefault().EmployeeNo,
Dept=g.FirstOrDefault().TimeSheetCategory,
日期=g.FirstOrDefault().日期,
FnGrHrs=g.Where(w=>w.TimeSheetCategory==“FN”和&!w.ItemID.StartsWith(“090”).Sum(h=>h.hours产生),
FnTlHrs=g.Where(w=>w.ItemID.StartsWith(“090”)).Sum(h=>h.ProcessDuration)>0?(g.FirstOrDefault(w=>w.TimeSheetCategory==“FN”).HoursWorked)-(g.Where(w=>w.ItemID.StartsWith(“090”).Sum(h=>h.ProcessDuration)):g.FirstOrDefault(w=>w.TimeSheetCategory=>w.TimeSheetCategory==“FN”).HoursWorked,
RmGrHrs=g.Where(w=>w.TimeSheetCategory==“RM”).Sum(h=>h.hoursProducted),RmGrHrsNet=g.Where(w=>w.TimeSheetCategory==“RM”).Sum(h=>h.hoursProductedNet),
RmTlHrs=g.FirstOrDefault(w=>w.TimeSheetCategory==“RM”)。工作小时数,
MpGrHrs=g.Where(w=>w.TimeSheetCategory==“MATPREP”).Sum(h=>h.HoursProducted),
MpTlHrs=g.FirstOrDefault(w=>w.TimeSheetCategory==“MATPREP”)。工作时间,
DtHrs=g.Sum(s=>s.DowntimeHours),
间接=g.Where(w=>w.ItemID.StartsWith(“090”)).Sum(h=>h.ProcessDuration)
});
返回query.ToList();
}
前几位只是收集数据,最后一个查询是过程的“肉”,需要时间
我相当肯定我做了一些可怕的事情,因为它吐出的SQL非常糟糕,但就我而言,我看不出如何改进它
非常感谢您的任何提示
Gordon您的表达式在iQuery编译和SQL server查询优化中都得到了优化,即使在这里也需要很长时间。很有可能您没有执行计划更快所需的列索引。将呈现的SQL表达式复制/粘贴到SSMS,运行它并查看实际计划。如果需要,优化数据库结构(放置索引)。否则,您会得到大量数据,这会使处理速度变慢。嗯。。。您能将粘贴呈现的SQL查询复制到SSMS中,运行,然后查看执行计划并检查是否存在所有需要的索引吗?如果您只提取大约500条记录,对FlatQuery执行ToList()并将其全部提取到内存中不是更简单吗?@RobLyndon的选项看起来也不错,但从未使用过。看起来它将在执行之前具体化数据,所以数据将首先从服务器中提取。我不确定这对这种情况是不是一个好的选择。吉姆,我应该先看一下索引,添加一个索引,现在查询只需要不到一秒钟的时间,改进了30倍。@GordonCopestack很高兴能帮助你