DataTable分组过滤异常:仍返回含1st installment的UnitNr数据
解决DataTable分组过滤异常:保留仅含Deposit且无1st Installment的UnitNr
你当前的问题核心是过滤逻辑写反了——原代码只检查了分组里存在Deposit事件的行,但没排除那些同时包含"1st installment"事件的分组,所以导致不符合要求的UnitNr被错误保留了。
问题分析
原过滤条件:
.Where(grp => grp.Any(x => x.Field<string>("Event") != "1st installment" && x.Field<string>("Event") == "Deposit"));
这个逻辑的意思是:只要分组里有任意一行是Deposit(且不是1st installment),就保留该分组。但如果某个UnitNr的分组里同时有Deposit和1st installment,这个条件依然会成立——因为确实存在Deposit的行,这就违反了“无1st installment”的核心要求。
正确的过滤逻辑
我们需要同时满足两个严格条件:
- 该分组完全不存在"1st installment"事件的行
- 该分组至少存在一个Deposit事件的行
修改后的完整代码
下面是修复后的test方法,同时包含将过滤后的数据存入新DataTable并绑定到GridView的完整逻辑:
private static void test(DataTable dt, RadGridView grid) { // 按UnitNr分组,并过滤出符合要求的分组 var validGroups = dt.AsEnumerable() .GroupBy(x => x.Field<string>("UnitNr")) .Where(grp => // 条件1:分组中没有任何"1st installment"事件(忽略大小写避免匹配误差) !grp.Any(x => x.Field<string>("Event").Equals("1st installment", StringComparison.OrdinalIgnoreCase)) && // 条件2:分组中至少有一个Deposit事件 grp.Any(x => x.Field<string>("Event").Equals("Deposit", StringComparison.OrdinalIgnoreCase)) ); // 创建新的DataTable,结构和原表完全一致 DataTable filteredDt = dt.Clone(); // 将符合条件的分组中的所有行导入新表 foreach (var group in validGroups) { foreach (var row in group) { filteredDt.ImportRow(row); } // 如果你只需要每组的特定行(比如最新的Deposit记录),可以用下面的逻辑替换上面的遍历: // var latestRow = group.OrderByDescending(x => x.Field<DateTime>("Date")).First(); // filteredDt.ImportRow(latestRow); } // 绑定到GridView grid.DataSource = filteredDt; grid.DataBind(); // 按需手动触发绑定 }
额外优化说明
- 用
StringComparison.OrdinalIgnoreCase做字符串比较:避免数据库中事件名大小写不一致(比如"1st Installment"首字母大写)导致的判断错误 - 可按需调整行保留逻辑:如果不需要每组的所有行,只需要特定记录(比如最新的Deposit行),可以启用注释里的排序筛选代码
- 原
GetNextPayments方法需要传入GridView实例,更新调用逻辑:
// 在GetNextPayments方法里修改调用 test(dt, Grid);
内容的提问来源于stack exchange,提问作者Taco2
相关产品推荐
相关产品推荐

