今天遇到一个非常难找的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个人的正常班产量。所以以后要注意了,改写循环里就写循环里!
当然,也不是说所有情况都要放循环里,特殊情况特殊对待!