Introduction

Working with DataTable objects is common when dealing with database operations, particularly in legacy systems or when using ADO.NET. However, for modern C# applications, it is often more convenient and type-safe to work with a list of strongly-typed objects instead of rows and columns. This guide will show you how to convert a DataTable to a List<T> in C# efficiently.

By the end of this article, you'll understand.

Let's dive in!

Why Convert a DataTable to a List of Objects?

Using a strongly-typed list instead of a generic DataTable provides several benefits.

When working in modern C# applications (like ASP.NET MVC, WebAPI, or Blazor), using strongly-typed models greatly improves maintainability and reduces bugs.

Method 1. Manual Conversion

The most basic way to convert a DataTable is by manually looping through its rows and creating objects.

Example

public List<User> ConvertDataTableToUserList(DataTable table)
{
    var users = new List<User>();
    foreach (DataRow row in table.Rows)
    {
        var user = new User
        {
            Id = Convert.ToInt32(row["Id"]),
            Name = row["Name"].ToString(),
            Email = row["Email"].ToString()
        };
        users.Add(user);
    }
    return users;
}

Here, User is a simple POCO class.

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
}

Explanation

Method 2. Using Reflection (Generic and Reusable)

Reflection allows a more dynamic and reusable way to map columns to properties automatically.

Generic Converter Method

public static List<T> ConvertDataTable<T>(DataTable table) where T : new()
{
    List<T> data = new List<T>();

    foreach (DataRow row in table.Rows)
    {
        T item = new T();
        foreach (var prop in typeof(T).GetProperties())
        {
            if (table.Columns.Contains(prop.Name) && row[prop.Name] != DBNull.Value)
            {
                prop.SetValue(item, Convert.ChangeType(row[prop.Name], prop.PropertyType));
            }
        }
        data.Add(item);
    }
    return data;
}

Usage Example

DataTable table = GetUsersDataTable(); // Your method to get a DataTable
List<User> users = ConvertDataTable<User>(table);

Explanation

Caution: Reflection can have a small performance cost. If you have a very large dataset, consider caching property info for optimization.

Bonus: LINQ Approach (when possible)

If you prefer a more LINQ-focused syntax (still using some manual mapping), you can do.

var users = (from DataRow row in table.Rows
             select new User
             {
                 Id = Convert.ToInt32(row["Id"]),
                 Name = row["Name"].ToString(),
                 Email = row["Email"].ToString()
             }).ToList();

Explanation

Best Practices

Conclusion

Converting a DataTable to a List<T> is a common requirement in C# projects. Whether you do it manually, via reflection, or using LINQ, each approach has its trade-offs. Reflection offers the most reusable pattern, but it can be slower for extremely large datasets. In professional applications, it's advisable to create utilities or helper libraries for these conversions. Once you have a solid method in place, working with clean, strongly-typed objects becomes easy and efficient!