为何Workflow伪代码中的foreach循环会执行两次?
先把你提供的Workflow伪代码整理出来方便分析:
drpQryStr = "very long query string" dataSet = new DataSet() dataSet = ExecuteQuery if dataSet.Tables[0].Rows.Count > 0 foreach (DataRow row in dataSetTables[0] as Enumerable()) iter = 0 dict = new Dictionary<string, string>() lst = new List<char>() newDict = new Dictionary<string, string>() sb = new StringBuilder() Do dict.Add(row.Table.Columns[iter].ColumnName, row[row.Table.Columns[iter].ColumnName].ToString()) iter ++ While(iter < row.Table.Columns.Count) foreach (KeyValuePair kv in dict) if(kv.Key == "DOB" || kv.Key == "LOB") newDict.Add(kv.Key, kv.Value) else strKey = kv.Key strCaseCorrected = strKey.ToLower() aChars = strCaseCorrected.ToCharArray() lst.Clear() sb.Clear() lst.AddRange(aChars) itr2 = 0 Do if(itr2 == 0) lst[itr2] = Char.ToUpper(lst[itr2]) else if(lst[itr2] == '_') itr2 ++ lst[itr2] = Char.ToUpper(lst[itr2]) else if(lst.Count - itr2 == 1) if(lst[itr2] == 'd') if(lst[itr2 - 1] == 'I') lst[itr2] = 'D' itr2 ++ While(itr2 < lst.Count) foreach(Char c in lst) sb.Append(c.ToString()) newDict.Add(sb.ToString(), kv.Value) dict = newDict dict[Communiction_Date] = dict["Communication_Date"].Insert(4, "-").Insert(7, "-") strJson = JsonConvert.SerializeObject(dict, Formatting.None) today = DateTime.Now.ToString("MM-dd-yyyy HH:mm:ss") Invoke a Rest Service that posts this json to a sqlless DB eventStr = "a large string that likely doesn't cause the problem" ctdbObj = JObject.Parse(eventStr) Invoke a Rest Service that Posts an event to a sqlless DB cts_id = dict["External_Source_ID"] strInsert = "sql insert statement" Execute Insert statement SendResponse
针对你遇到的foreach循环内部操作重复执行的问题,我从几个常见的排查方向给你分析:
检查DataSet返回的数据源是否重复
先确认ExecuteQuery返回的dataSet.Tables[0]里的行数是否符合预期。如果你的查询语句drpQryStr本身返回了重复的行(比如关联表时产生笛卡尔积、没加DISTINCT去重),那循环多执行就是正常的。可以在循环前加个日志输出dataSet.Tables[0].Rows.Count的值,对比实际应该处理的数据量。排查工作流是否被重复触发
因为这是工作流引擎,很可能是整个工作流被触发了两次。比如:- 工作流的触发器(比如API请求、定时任务、事件)被触发了两次;
- 工作流节点配置了重试机制,比如Rest调用失败后自动重试,但其实第一次调用已经成功了;
SendResponse之后的回调逻辑又触发了当前工作流。
可以查看工作流的执行日志,看是否有两次完整的流程执行记录。
检查foreach循环的语法/枚举问题
你的伪代码里foreach (DataRow row in dataSetTables[0] as Enumerable())看起来有笔误,应该是dataSet.Tables[0]吧?如果实际代码中把DataTable转成Enumerable时出现异常,或者不小心重复枚举了集合(比如多次调用AsEnumerable()并遍历),也可能导致重复执行。另外,某些LINQ操作如果没有正确缓存结果,也可能导致多次枚举。外部操作的回调触发工作流
你在循环里调用了两个Rest服务和一个数据库插入操作,有没有可能这些外部服务执行完成后,通过webhook或者其他方式回调了你的工作流,导致整个流程重新执行?可以检查外部服务的日志,看是否有两次请求记录,同时对比工作流的触发时间和外部服务的回调时间。工作流引擎的状态管理BUG
部分工作流引擎在处理持久化状态时可能存在问题,比如当工作流执行到外部调用节点时会持久化状态,如果恢复时引擎错误地重复执行了循环体,也会出现这种情况。可以查看工作流的活动执行日志,确认是整个循环执行了两次,还是循环内的某个节点被重复执行。
内容的提问来源于stack exchange,提问作者pchancey

