DataTable自定义孤行剔除逻辑未生效,请求排查问题
DataTable孤行查找与剔除逻辑问题
我尝试给DataTable实现孤行查找和剔除逻辑:如果某条记录的第26列数值没有出现在任意行的第21列中,就判定该行是孤行并删除。但当前代码没按预期运行,甚至根本进不了if(occurance == 0)分支。为了避免DataTable索引混乱,我设置每次只删除一行,保存到Session后重启逻辑直到没有孤行,代码如下:
DataTable t = Session["SessionData"] as DataTable; DataRow[] rows = t.Select(); int occurance; int n = 0; string Orphan = ""; for (int i = 0; i < rows.Length; i++) { if(rows[i][26].ToString() != "0")//An additional condition that shouldn't affect { occurance = 0; for (int j = 0; j < rows.Length; j++) { if (j != i) { n = i; if (rows[i][26].ToString() == rows[j][21].ToString()) { occurance = 1; break; } } } if(occurance == 0) { Orphan = rows[n][26].ToString(); t.Rows[n].Delete(); t.AcceptChanges(); Session["SessionData"] = t; break; } } } if(!string.IsNullOrEmpty(Orphan)) { ClearOrphans(null, null); }
问题根源
- 快照数组与DataTable不同步:
t.Select()返回的是DataTable的行快照,后续修改DataTable不会更新这个数组,递归调用时重新获取的快照和第一次循环的快照存在差异,容易导致判断偏差。 - 错误排除当前行匹配:内层循环加了
j != i的判断,如果某行的第26列值仅出现在自己的第21列中,会被错误处理;但你的情况是进不了occurance==0分支,更可能是字符串匹配的隐藏问题。 - 字符串比较的潜在问题:直接用
ToString()比较,可能存在数值转字符串的格式差异(比如123和123.0)、前后空格等情况,导致本该不匹配的被错误匹配,进而无法触发孤行判定。 - 多余变量引发索引混乱:
n变量仅在j != i时赋值,若j=i则n保留之前的值,可能导致删除错误行,也干扰了逻辑判断的准确性。
修复后的代码
DataTable t = Session["SessionData"] as DataTable; // 先把所有第21列的有效值存入HashSet,大幅提升查找效率 HashSet<string> col21Values = new HashSet<string>(); foreach (DataRow row in t.Rows) { string val = row[21].ToString().Trim(); if (!string.IsNullOrEmpty(val)) { col21Values.Add(val); } } string orphanValue = ""; int deleteIndex = -1; // 遍历找到第一个符合条件的孤行 for (int i = 0; i < t.Rows.Count; i++) { DataRow row = t.Rows[i]; string col26Val = row[26].ToString().Trim(); // 满足两个条件:第26列不是0,且不在第21列的集合中 if (col26Val != "0" && !col21Values.Contains(col26Val)) { orphanValue = col26Val; deleteIndex = i; break; } } if (deleteIndex != -1) { t.Rows[deleteIndex].Delete(); t.AcceptChanges(); Session["SessionData"] = t; // 递归继续清理剩余孤行 ClearOrphans(null, null); }
修复说明
- 用HashSet优化性能:原来的双层循环是O(n²)复杂度,HashSet查找是O(1),数据量大时效率提升明显。
- 修正匹配逻辑:去掉
j != i的限制,如果你实际需求是必须出现在其他行的第21列,可在构建HashSet时跳过当前行;按需求描述“任意行”,保留所有行的第21列值。 - 处理字符串空格:用
Trim()避免前后空格导致的匹配失败。 - 直接操作DataTable行集合:不再依赖快照数组,彻底避免不同步问题。
- 简化变量逻辑:去掉多余的
n和occurance变量,直接记录要删除的索引,逻辑更清晰。
内容的提问来源于stack exchange,提问作者Barnabeck
相关产品推荐
相关产品推荐

