Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Convert a Generic List to a Datatable

0.00/5 (No votes)
23 May 2010 1  
A Generic List with a feature of converting itself to a DataTable

Preface

There are several cases when we feel the need to convert a List of objects into a DataTable. There is a case where I particularly feel this need.

When we are using an object oriented approach in our web application, it is always better to bind the GridView with a generic List of objects. The sorting of the GridView becomes a problem in this case as the C# .NET Generic List class does not provide an easy sorting functionality.

Traditionally (the sorting solution for GridView in almost all the .NET articles), we sort a GridView by converting the source datatable into a DataView and binding the GridView again with the sorted DataView. This is a very easy method for GridView sorting.

So, if we are binding GridView with List of objects, we feel the need to convert it to a DataTable at the time of sorting.

Since the generic class List doesn’t provide a function to convert to DataTable, I created a class ABList which has this functionality.

Hence, one can use ABList the same way as one will use List, the only difference will be an additional function GetDataTable.

I hope now I have justified the purpose of writing this article, so we can move forward to look at the working of ABList.

Introduction

ABList is a generic class which inherits System.Generics.Collections.List. It adds a public function GetDataTable and thus extends its functionality to get a DataTable containing all the public properties as columns for the underlying class, and a row for each object in the List.

It can be used to create a List of any data type whether a reference type or value type. If the underlying type is a reference type, except String, it will have columns same as all the public properties of that class. If it is a value type, then only one column will be there called “Value”, which will store the value of the variables in List.

How to Use ABList Class

Using ABList class is as simple as using a List class. We need to define a variable by providing the underlying type we want to use with our ABList class, as:  

ABList<Product> lstP = new ABList<Product>();

Then we can add items to this list, as:

lstP.Add(new Product("a", "a"));
lstP.Add(new Product("b", "b"));
lstP.Add(new Product("c", "c"));

Just the way we do it with List.

Now, if we want our List to be converted into a DataTable, we just need to call a new function defined in ABClass:

DataTable dtPro = lstP.GetDataTable();

The ABList Class

The ABList class is inheriting a generic class List, it has only one function of its own, the GetDataTable function. Following is the way ABList has been defined:

public class ABList<T> : List<T>

Simple.

Then there is the GetDataTable function. I have not constrained the ABList for reference type or value type only. So we need to take care of both the cases while converting the List into DataTable as the underlying type can be both value or reference type.

First, we check how to get a DataTable if the underlying type is a value type (or string).

In value type, the DataTable is expected to contain the values of all the variables (items) present in List. Hence we create only one column in the DataTable named “Value”, and add a new row for each item found in the List saving its value in the row.

if (typeof(T).IsValueType || typeof(T).Equals(typeof(string)))
{
   DataColumn dc = new DataColumn("Value");
   dt.Columns.Add(dc);
   foreach (T item in this)
   {
       DataRow dr = dt.NewRow();
       dr[0] = item;

       dt.Rows.Add(dr);
   }
}

Though String is a reference type, due to its behavior we treat it as a special case and handle it as value type only.

Now, for handling reference type, we need to make use of PropertyInfo class of System.Reflection namespace.

First, we find out all the public properties of the underlying class using Reflection, as:

PropertyInfo[] piT = typeof(T).GetProperties();

So, we have all the public properties of the underlying class, now we need to create a DataTable and set column names to be property names in the array piT.

foreach (PropertyInfo pi in piT)
{
   //create a datacolumn for each property
   DataColumn dc = new DataColumn(pi.Name, pi.PropertyType);

   dt.Columns.Add(dc);
}

Then, we iterate through all the items in the List and create a row for each item saving values of properties in the corresponding columns. To get the value of a property from the object (item), we need to call the GetValue method for each property in our array of PropertyInfo piT.

for (int item = 0; item < this.Count; item++)
{
    DataRow dr = dt.NewRow();

     for (int property = 0; property < dt.Columns.Count; property++)
     {
        dr[property] = piT[property].GetValue(this[item], null);
     }

     dt.Rows.Add(dr);
}

History

  • 23rd May, 2010: Initial post

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here