如何用LINQ高效筛选DataTable/DataView中匹配双值对的行?
用LINQ优化匹配查询的方案
当然可以用LINQ实现,而且能大幅提升查询效率——核心思路是提前构建哈希索引,避免嵌套循环中重复遍历全量数据。以下是两种实用的实现方式:
方式一:预分组构建字典(推荐,查找效率最高)
先将全量数据按msdyn_workorderid和msdyn_workorderproductid的组合分组,存入字典作为索引,之后遍历去重表时直接通过键值对快速查找:
// 1. 提前为全量数据构建组合键索引(仅需执行一次) var groupedFullData = CRMDataSetSent_Dt.AsEnumerable() .GroupBy(row => new { WorkOrderId = row.Field<Guid>("msdyn_workorderid"), // 替换为实际字段类型,比如string WorkOrderProductId = row.Field<Guid>("msdyn_workorderproductid") }) .ToDictionary(group => group.Key, group => group.ToList()); // 2. 遍历去重表,快速获取匹配行 foreach (DataRow distinctRow in distinct_Wo_Wop_Dt.Rows) { var lookupKey = new { WorkOrderId = distinctRow.Field<Guid>("msdyn_workorderid"), WorkOrderProductId = distinctRow.Field<Guid>("msdyn_workorderproductid") }; if (groupedFullData.TryGetValue(lookupKey, out var matchedRows)) { // 处理匹配到的行,比如执行业务逻辑 foreach (var matchedRow in matchedRows) { // 你的业务代码,例如: // Console.WriteLine(matchedRow.Field<string>("some_column")); } } }
方式二:LINQ Join关联查询
直接利用LINQ的Join操作,内部会自动基于哈希表实现高效关联,代码更简洁:
// 通过Join关联两个DataTable,获取所有匹配的行对 var matchedResults = from distinctRow in distinct_Wo_Wop_Dt.AsEnumerable() join fullRow in CRMDataSetSent_Dt.AsEnumerable() on new { WoId = distinctRow.Field<Guid>("msdyn_workorderid"), WopId = distinctRow.Field<Guid>("msdyn_workorderproductid") } equals new { WoId = fullRow.Field<Guid>("msdyn_workorderid"), WopId = fullRow.Field<Guid>("msdyn_workorderproductid") } select new { DistinctRow = distinctRow, FullRow = fullRow }; // 遍历结果处理业务逻辑 foreach (var result in matchedResults) { // 使用result.DistinctRow(去重表的行)和result.FullRow(全量表的匹配行) }
为什么比foreach循环高效?
原来的foreach嵌套遍历是O(n*m)的时间复杂度(n是去重表行数,m是全量表行数),而LINQ的GroupBy/Join都是基于哈希表实现,构建索引是O(m),后续每次查找是O(1),整体复杂度降到O(n+m),数据量越大,性能提升越明显。
注意事项
- 确保两个表中对应字段的数据类型完全一致(比如都是Guid或string),否则会出现匹配失败;如果字段允许为空,需要额外处理
DBNull.Value的情况。 - 如果全量表数据量极大,可考虑分批处理避免内存压力,但常规场景下上述方案的内存占用是可接受的。
内容的提问来源于stack exchange,提问作者gymcode
相关产品推荐
相关产品推荐

