Paul On Technology

Exploring technology

Converting objects or arrays of objects to DataTables

Recently there have been some articles about not using DataSets or DataTables in web applications. Scott Mitchell has Why I Don't Use DataSets in My ASP.NET Applications and More On Why I Don't Use DataSets in My ASP.NET Applications. Karl Sequin has On the Way to Mastering ASP.NET: Introducing Custom Entity Classes.

I prefer to use custom objects also, mostly because I like to abstract the database away from the client app. So I have this API with custom classes (fed from DataReaders) and a coworker wants to use my API to drive some reports. The only problem is the tool they are using doesn't work with arrays of objects. They say it needs DataSets, DataTables or DataReaders.

At first I started getting nervous but then I thought about it. DataSets and DataTables are fed from DataReaders. That's when I said to myself, "Self, you can feed DataSets and DataTables from your custom classes by using reflection."

Now I am far from a Reflection guru, but all they need are column names,  data types and values. I can build DataColumns from the property info of classes dynamically using Reflection. The following code is my first pass. If anyone sees a way to improve on this then by all means, let's hear it.

using System;

using System.Data;

using System.Reflection;

using System.Reflection.Emit;

 

namespace ObjToAdo

{

        /// <summary>

        /// Summary description for Converter.

        /// </summary>

        public class Converter

        {

                private Converter()     {}

 

                /// <summary>

                ///

                /// </summary>

                /// <param name="o"></param>

                /// <returns></returns>

                public static DataTable ConvertToDataTable(Object o)

                {      

                        PropertyInfo[] properties = o.GetType().GetProperties();

                        DataTable dt = CreateDataTable(properties);

                        FillData(properties, dt, o);

                        return dt;

                }

 

                /// <summary>

                ///

                /// </summary>

                /// <param name="o"></param>

                /// <returns></returns>

                public static DataTable ConvertToDataTable(Object[] array)

                {

                        PropertyInfo[] properties = array.GetType().GetElementType().GetProperties();

                        DataTable dt = CreateDataTable(properties);

 

                        if (array.Length != 0)

                        {

                                foreach(object o in array)

                                        FillData(properties, dt, o);

 

                        }

 

                        return dt;

                }

 

                /// <summary>

                ///

                /// </summary>

                /// <param name="properties"></param>

                /// <returns></returns>

                private static DataTable CreateDataTable(PropertyInfo[] properties)

                {

                        DataTable dt = new DataTable();

                        DataColumn dc = null;

 

                        foreach(PropertyInfo pi in properties)

                        {

                                dc = new DataColumn();

                                dc.ColumnName = pi.Name;

                                dc.DataType = pi.PropertyType;

                               

                                dt.Columns.Add(dc);                            

                        }

 

                        return dt;

                }

 

 

                /// <summary>

                ///

                /// </summary>

                /// <param name="properties"></param>

                /// <param name="dt"></param>

                /// <param name="o"></param>

                private static void FillData(PropertyInfo[] properties, DataTable dt, Object o)

                {

                        DataRow dr = dt.NewRow();

 

                        foreach(PropertyInfo pi in properties)

                                dr[pi.Name] = pi.GetValue(o, null);

 

                        dt.Rows.Add(dr);       

                }

 

 

        }

}

 

 

 

Comments

ramana said:

How call the above methods(ConvertToDataTable() )from front end or

how to send object from front end to ConvertToDataTable(object source).please send as ssonas possible

# November 6, 2007 6:38 AM

Adam Kahtava said:

Thanks Paul,

I just used your approach and a derivation of your code in my project.

-Adam

# November 28, 2007 12:08 PM

K. Thilakar said:

Really good code to do the conversion.  Helped me a lot.  Thanks a lot for sharing this code.

# July 1, 2009 7:05 AM

JM said:

Great code, thanks!

# January 6, 2010 11:37 AM

Imaging Team said:

Thanks for the Code!!!It works fine.

# March 3, 2010 5:52 AM

neha said:

really gud code thanks

# March 6, 2010 5:37 AM

DrivenTooFar said:

This was great and it worked perfectly.

# May 7, 2010 7:57 AM

sbsdevelop said:

Awesome post!

I modified two routines to support nullable types too...

           private static DataTable CreateDataTable(PropertyInfo[] properties)

           {

               DataTable dt = new DataTable();

               DataColumn dc = null;

               NullableConverter nc;

               foreach (PropertyInfo pi in properties)

               {

                   Type theType;

                   if (IsNullableType(pi.PropertyType))

                   {

                       nc = new NullableConverter(pi.PropertyType);

                       theType = nc.UnderlyingType;

                       nc = null;

                   }

                   else

                   {

                       theType = pi.PropertyType;

                   }

                   dc = new DataColumn();

                   dc.ColumnName = pi.Name;

                   dc.DataType = theType;

                   dt.Columns.Add(dc);

               }

               return dt;

           }

           private static void FillData(PropertyInfo[] properties, DataTable dt, Object o)

           {

               DataRow dr = dt.NewRow();

               foreach (PropertyInfo pi in properties)

                   dr[pi.Name] = pi.GetValue(o, null) != null ? pi.GetValue(o, null) : DBNull.Value;

               dt.Rows.Add(dr);

           }

           private static bool IsNullableType(Type theType)

           {

               return (theType.IsGenericType && theType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));

           }

# November 17, 2010 3:10 AM

rani said:

how to call the above methods please send as early as passible quick it's urgent

thanks and regards

# January 11, 2011 2:27 AM

CP_GSM said:

Hi,

Thanks for the code. I'am getting an exception {"Parameter count mismatch."} on the following line.

dr[pi.Name] = pi.GetValue(o, null) != null ? pi.GetValue(o, null) : DBNull.Value;

can someone explain the line please?

Thanks

# September 3, 2011 9:52 AM

Sam said:

Really thanks Paul,

Your code has just solve my one of the problem in recent project.

# September 5, 2011 1:47 AM

fereshteh said:

Thanks,It really helped me:)

# November 19, 2012 2:22 AM