今天收到客户提出的一个bug,如下段代码,非常卡,跑代码是直接卡住十几秒。
public List<IHDCpoeExam> GetCpoeExamList(IHDCpoeExam clsCpoeExam)
{
List<IHDCpoeExam> lstCpoeExam = examRptPatterRule.Value.GetCpoeExamList(clsCpoeExam);
var clsCpoeExamDetail = new IHDCpoeExamDetail();
clsCpoeExamDetail.ExamReqNolst = clsCpoeExam.ExamReqNolst; //多个申请
clsCpoeExamDetail.ExamReqNo = clsCpoeExam.ExamReqNo; //单个申请
List<IHDCpoeExamDetail> lstCpoeExamDetail = examRptPatterRule.Value.GetCpoeExamDetailList(clsCpoeExamDetail);
foreach (var item in lstCpoeExam)
{
item.lstCpoeExamDetail = new List<IHDCpoeExamDetail>();
item.lstCpoeExamDetail.AddRange(lstCpoeExamDetail.FindAll(x => x.ExamReqNo == item.ExamReqNo));
}
return lstCpoeExam;
}
可以看出,当参数clsCpoeExam里面的ExamReqNolst和ExamReqNo两个参数都为空的时候,下面的GetCpoeExamDetailList方法就是全表查询了,这个表为检查项目明细表,数据量非常大,就会导致卡慢。
今天我第一时间想到的是就是把前面lstCpoeExam集合里面的ReqNo收集到给到ExamReqNolst作为参数,防止全表查,就是下面的代码,给到查询方法就是一个in的查询,速度确实是快了,因为有了条件
public List<IHDCpoeExam> GetCpoeExamList(IHDCpoeExam clsCpoeExam)
{
List<IHDCpoeExam> lstCpoeExam = examRptPatterRule.Value.GetCpoeExamList(clsCpoeExam);
if (lstCpoeExam?.Count > 0)
{
var clsCpoeExamDetail = new IHDCpoeExamDetail();
clsCpoeExamDetail.ExamReqNolst = clsCpoeExam.ExamReqNolst; //多个申请
clsCpoeExamDetail.ExamReqNo = clsCpoeExam.ExamReqNo; //单个申请
if (clsCpoeExam.ExamReqNolst?.Count < 1 && !clsCpoeExam.ExamReqNo.HasValue)
{
clsCpoeExamDetail.ExamReqNolst = new List<int>();
lstCpoeExam.ForEach(exam => {
clsCpoeExamDetail.ExamReqNolst.Add((int)exam.ExamReqNo);
});
}
List<IHDCpoeExamDetail> lstCpoeExamDetail = examRptPatterRule.Value.GetCpoeExamDetailList(clsCpoeExamDetail);
foreach (var item in lstCpoeExam)
{
item.lstCpoeExamDetail = new List<IHDCpoeExamDetail>();
item.lstCpoeExamDetail.AddRange(lstCpoeExamDetail.FindAll(x => x.ExamReqNo == item.ExamReqNo));
}
}
return lstCpoeExam;
}
此时,我突然想起,另外一个项目之前也反应过这个问题,我去看看之前我是怎么改的,结果一看,确实有改动过,但是改的代码却不一样。如下:
public List<IHDCpoeExam> GetCpoeExamList(IHDCpoeExam clsCpoeExam)
{
List<IHDCpoeExam> lstCpoeExam = examRptPatterRule.Value.GetCpoeExamList(clsCpoeExam);
var clsCpoeExamDetail = new IHDCpoeExamDetail();
clsCpoeExamDetail.ExamReqNolst = clsCpoeExam.ExamReqNolst; //多个申请
clsCpoeExamDetail.ExamReqNo = clsCpoeExam.ExamReqNo; //单个申请
if (!string.IsNullOrEmpty(clsCpoeExam.PatId))
{
clsCpoeExamDetail.PatId = clsCpoeExam.PatId;
}
if (clsCpoeExam.VisitId.HasValue)
{
clsCpoeExamDetail.VisitNo = clsCpoeExam.VisitId;
}
List<IHDCpoeExamDetail> lstCpoeExamDetail = examRptPatterRule.Value.GetCpoeExamDetailList(clsCpoeExamDetail);
foreach (var item in lstCpoeExam)
{
item.lstCpoeExamDetail = new List<IHDCpoeExamDetail>();
item.lstCpoeExamDetail.AddRange(lstCpoeExamDetail.FindAll(x => x.ExamReqNo == item.ExamReqNo));
}
return lstCpoeExam;
}
可以看到,用的是两个pid和VisitNo两个值来进行等于的匹配,这种方式就是下面的两个=的条件,在数据库中,B表的Pat_id 和Visit_id都是有索引的字段,那么这种方式其实会更加快速,较之上面的in的查询方法。
所以,不同时间我们想到的解决方法是不同的,有时候为了解决bug,并不会去考虑那种方法的使用会更加的有效便捷,今天碰到这个问题,写下来的目的就是提醒自己,后面再写代码的时候,不能只顾达到目的,还得保证代码的效率和便捷。