Comprehensive Guide to Group-Based Deduplication in DataTable Using LINQ

Nov 26, 2025 · Programming · 7 views · 7.8

Keywords: C# | DataTable | LINQ Grouping | Data Deduplication | CopyToDataTable

Abstract: This technical paper provides an in-depth analysis of group-based deduplication techniques in C# DataTable. By examining the limitations of DataTable.Select method, it details the complete workflow using LINQ extensions for data grouping and deduplication, including AsEnumerable() conversion, GroupBy grouping, OrderBy sorting, and CopyToDataTable() reconstruction. Through concrete code examples, the paper demonstrates how to extract the first record from each group of duplicate data and compares performance differences and application scenarios of various methods.

Analysis of DataTable.Select Method Limitations

In C# data processing, the DataTable.Select method is often misunderstood as supporting full SQL syntax. In reality, this method only supports simple filter expressions like {field} = {value} and cannot handle complex GROUP BY operations. When developers attempt to use SQL statements such as SELECT MIN(PK), Col1, Col2 GROUP BY Col1, Col2, the system throws exceptions because DataTable.Select is essentially a row filter rather than a complete query engine.

LINQ-Based Group Deduplication Solution

To address group-based deduplication in DataTable, using LINQ to DataSet extension methods is recommended. The core approach involves converting DataTable to Enumerable, leveraging LINQ's powerful grouping capabilities, and finally converting the results back to DataTable.

Basic Implementation Code

DataTable dt = GetSampleDataTable();
dt = dt.AsEnumerable()
       .GroupBy(r => new { Col1 = r["Col1"], Col2 = r["Col2"] })
       .Select(g => g.OrderBy(r => r["PK"]).First())
       .CopyToDataTable();

Step-by-Step Code Analysis

AsEnumerable() Conversion: Converts DataTable to IEnumerable<DataRow>, enabling LINQ operations. This serves as the crucial bridge connecting DataTable and the LINQ ecosystem.

GroupBy Grouping: Defines grouping keys using anonymous types new { Col1 = r["Col1"], Col2 = r["Col2"] }. All rows with identical Col1 and Col2 values are grouped together, forming IGrouping collections.

Sorting and Selection: Within each group, OrderBy(r => r["PK"]) sorts rows in ascending order by PK field, then First() selects the first record from each group. This ensures the returned rows have the smallest PK values within their respective groups.

Data Reconstruction: The CopyToDataTable() method reassembles the filtered DataRow collection into a new DataTable, completing the entire deduplication process.

Performance Optimization and Considerations

When processing large datasets, it's advisable to apply appropriate indexing or sorting to the source data first. For extremely large datasets, consider using Parallel LINQ (PLINQ) to enhance processing efficiency:

dt = dt.AsEnumerable().AsParallel()
       .GroupBy(r => new { Col1 = r["Col1"], Col2 = r["Col2"] })
       .Select(g => g.OrderBy(r => r["PK"]).First())
       .CopyToDataTable();

Comparison with Alternative Methods

Compared to traditional manual loop-based deduplication methods, the LINQ approach offers better readability and maintainability. When contrasted with the string concatenation method mentioned in reference articles, this solution preserves the original data structure and type safety, avoiding potential issues from type conversions.

Extended Application Scenarios

This technique is not limited to simple deduplication needs but can be extended to complex data aggregation scenarios. For example, modifying the Select clause can implement statistical functions like summation and averaging:

var result = dt.AsEnumerable()
              .GroupBy(r => new { Col1 = r["Col1"] })
              .Select(g => new {
                  Col1 = g.Key.Col1,
                  Total = g.Sum(r => Convert.ToInt32(r["Col2"]))
              });

By flexibly utilizing various LINQ operators, developers can construct powerful and maintainable data processing pipelines, significantly improving development efficiency and code quality.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.