Efficient Conversion Methods from Generic List to DataTable

Nov 10, 2025 · Programming · 17 views · 7.8

Keywords: Generic List | DataTable Conversion | Reflection Mechanism | FastMember | Performance Optimization

Abstract: This paper comprehensively explores various technical solutions for converting generic lists to DataTable in the .NET environment. By analyzing reflection mechanisms, FastMember library, and performance optimization strategies, it provides detailed comparisons of implementation principles and performance characteristics. With code examples and performance test data, the article offers a complete technical roadmap from basic implementations to high-performance solutions, with special focus on nullable type handling and memory optimization.

Introduction

In modern software development, data structure conversion is a common programming requirement. Particularly in enterprise-level applications, there is often a need to convert in-memory object collections to relational data structures for data binding, report generation, or database operations. This paper systematically explores how to efficiently convert generic lists to DataTable, a process that involves not only type system mapping but also considerations for performance and memory usage optimization.

Basic Reflection Implementation

The most straightforward implementation approach utilizes the reflection mechanism provided by the .NET framework. Through the TypeDescriptor.GetProperties method, property descriptor collections of types can be obtained, enabling the construction of DataTable column structures. The following is a basic implementation example:

public static DataTable ToDataTable<T>(this IList<T> data)
{
    PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
    DataTable table = new DataTable();
    
    // Build column structure
    for(int i = 0 ; i < props.Count ; i++)
    {
        PropertyDescriptor prop = props[i];
        table.Columns.Add(prop.Name, prop.PropertyType);
    }
    
    // Populate data rows
    object[] values = new object[props.Count];
    foreach (T item in data)
    {
        for (int i = 0; i < values.Length; i++)
        {
            values[i] = props[i].GetValue(item);
        }
        table.Rows.Add(values);
    }
    return table;        
}

Although this method is intuitive, its performance is suboptimal when processing large amounts of data, as each property access requires going through the reflection mechanism, incurring significant overhead.

Improvements for Nullable Type Handling

In practical applications, it is often necessary to handle objects containing nullable types. The original implementation may not correctly process null values and nullable value types. Here is an improved version:

public static DataTable ToDataTable<T>(this IList<T> data)
{
    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
    DataTable table = new DataTable();
    
    foreach (PropertyDescriptor prop in properties)
        table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
    
    foreach (T item in data)
    {
        DataRow row = table.NewRow();
        foreach (PropertyDescriptor prop in properties)
             row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
        table.Rows.Add(row);
    }
    return table;
}

This improved version correctly handles nullable value types through the Nullable.GetUnderlyingType method and uses DBNull.Value to represent null values in databases, ensuring the accuracy of data conversion.

High-Performance Solution: FastMember Library

To significantly improve performance, the FastMember library developed by Marc Gravell can be used. This library provides property access capabilities close to native code performance through meta-programming techniques:

IEnumerable<SomeType> data = ...
DataTable table = new DataTable();
using(var reader = ObjectReader.Create(data)) {
    table.Load(reader);
}

If specific property members need to be specified or ordering enforced, property names can be explicitly designated:

IEnumerable<SomeType> data = ...
DataTable table = new DataTable();
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) {
    table.Load(reader);
}

FastMember internally uses dynamic code generation technology, avoiding the performance penalty associated with reflection, resulting in significant performance improvements in large-scale data processing scenarios.

Performance Comparison Analysis

To quantify the performance differences between different methods, we designed a test case. The test data includes 5000 MyData objects, with each test running 500 conversion operations:

public class MyData
{
    public int A { get; set; }
    public string B { get; set; }
    public DateTime C { get; set; }
    public decimal D { get; set; }
    public string E { get; set; }
    public int F { get; set; }
}

Performance test results show:

These results clearly demonstrate that optimizing the property access mechanism can yield nearly 4x performance improvement. When data volumes increase further, this performance difference becomes even more pronounced.

Architectural Design Considerations

When dealing with extremely large datasets, pure code optimization may not be sufficient to meet performance requirements. At this point, architectural-level optimizations need to be considered:

Database Integration Solution: For scenarios requiring frequent complex queries, sorting, and aggregation operations, directly storing data in relational databases may be a better choice. Database engines are specifically optimized to efficiently handle various operations on large-scale data.

Efficient Data Structure Selection: Choose appropriate data structures based on specific usage scenarios. For example, if frequent key-value lookup operations are needed, Dictionary<TKey, TValue> may be more efficient than List<T>, as the former provides near-constant-time lookup performance.

Practical Application Scenarios

List to DataTable conversion is particularly common in scenarios such as data import/export, report generation, and data binding. Especially when binding with UI controls (like GridView, DataGrid), DataTable provides rich functional support.

For scenarios like Excel data processing, while CopyToDataTable methods can directly handle IEnumerable<DataRow>, conversion methods discussed in this paper are still required when dealing with custom objects.

Best Practice Recommendations

Based on performance testing and practical application experience, we recommend the following best practices:

  1. For small to medium-scale data, use improved reflection implementations that balance development efficiency and performance
  2. For performance-sensitive large-scale data processing, prioritize high-performance libraries like FastMember
  3. In production environments, conduct thorough performance testing and select optimal solutions based on actual data characteristics
  4. Pay attention to memory management, promptly release unused DataTable objects to avoid memory leaks

Conclusion

Generic list to DataTable conversion is a common requirement in .NET development. This paper systematically introduces a complete technical roadmap from basic implementations to high-performance optimizations. Through reasonable architectural design and tool selection, developers can achieve excellent performance while maintaining code maintainability. In actual projects, the most suitable technical solution should be selected based on specific data scale, performance requirements, and development costs.

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.