今天遇到一个非常难找的Bug,记录下来以备不时之需。
做的这个程序是用来统计员工每天产量的,有正常班产量,和加班产量。如果该员工某天的产量已经提取过来,就更新原来记录。如果没有提取过就新增一条记录。
大概过程是这样的,假如有10个员工。
/// <param name="strType">1代表正常班产量 2代表加班产量</param>
private void GetWorkCount(string strType)
{
//创建产量记录Model
Model.WV_WorkRecord model = new Model.WV_WorkRecord();
for (int i = 0; i < 10; i++)
{
bool flag; //为了表示 是否存在产量记录
//员工ID
int lngUserID=i;
string strStartDate = "2020-01-01";
model.WorkerID = lngUserID;
//员工产量日期
model.WorkDate = strStartDate;
//
....这里写判断是否存在产量记录的代码
model2 = BLL.WV_WorkRecord.Instance.GetModel(" workId=" + lngUserID + " and workDate='" + strStartDate + "'");
///
if (flag) //是否存在 产量记录 存在更新原来记录,不存在添加一条记录
{
model = model2; //model2 是从数据库里取出来的原来就存在的那条记录
if (strType == "1")
{
//员工正常班产量
model.WorkCount = workCount;
}
else if (strType == "2")
{
//员工加班产量
model.WorkAddCount = workAddCount;
}
flag = BLL.WV_WorkRecord.Instance.Update(model);
}
else
{
if (strType == "1")
{
//员工正常班产量
model.WorkCount = workCount;
}
else if (strType == "2")
{
//员工加班产量
model.WorkAddCount = workAddCount;
}
flag = BLL.WV_WORKRECORDD.Instance.Add(model);
}
}
}
Model.WV_WorkRecord model = new Model.WV_WorkRecord(); 写在了for循环外。你觉得有问题没有?
我最开始写外边是考虑到放在循环里,每次循环都需要New一个对象,如果循环次数太多,是不是太浪费内存资源了,所以就提到了for循环外,结果就造成了错误,而且很难排查问题。因为只有极个别记录会有问题,所以也就造成了很难排查。
大家想一下这种情况,我现在要获取加班产量记录到数据库,如果第1个人在数据库里已经有了记录,这时候model就会指向数据库里已经有的那条记录的model,紧接着获取第2个人的加班产量,第2个人在数据库里没有过记录,
我要新增进去。你会发现你只通过 “model.WorkAddCount = workAddCount;” 这句代码修改了加班产量, 正常班产量确指向第1个人的正常班产量。所以以后要注意了,改写循环里就写循环里!
当然,也不是说所有情况都要放循环里,特殊情况特殊对待!