Paul On Technology

Exploring technology

Converting objects or arrays of objects to DataTables Part II

I have had a chance to work a little more on converting objects to data tables. Oddur has asked about nested types and I have implemented them - to an extent. The issue is how far do I really need to take this? Our needs are simple, but I did run into having to handle enums. I decided that an enum would always produce a String column and that I would use the enum name as the value.

Again, this is a work in progress and I need to refactor but I have it working. Here's the code and if anyone has any ideas then please leave a comment.

 

using System;

using System.Collections;

using System.Data;

using System.Reflection;

using System.Reflection.Emit;

 

namespace ObjToAdo

{

        /// <summary>

        ///             The Converter class provides methods to convert objects into data tables.

        /// </summary>

        public class Converter

        {

                /// <summary>

                ///             An array of the names of the System data types.

                /// </summary>

                private static String[] _systemTypes = new String[]{ "SYSTEM.BYTE", "SYSTEM.CHAR", "SYSTEM.DECIMAL", "SYSTEM.DOUBLE", "SYSTEM.INT16", "SYSTEM.INT32", "SYSTEM.INT64",

                                                                                                                "SYSTEM.SBYTE", "SYSTEM.SINGLE", "SYSTEM.UINT16", "SYSTEM.UINT32", "SYSTEM.UINT64", "SYSTEM.DATETIME",

                                                                                                                "SYSTEM.STRING", "SYSTEM.BOOLEAN" };

 

                private Converter(){}

 

                /// <summary>

                ///             Converts an object into a data table.

                /// </summary>

                /// <param name="source">Spcifies the object to convert into a data table.</param>

                /// <returns>Returns a data table created from an object.</returns>

                public static DataTable ConvertToDataTable(Object source)

                {      

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

                        DataTable dt = CreateDataTable(properties, source);

                        dt.TableName = source.GetType().Name;

                        FillData(properties, dt, null, String.Empty, source);

                        return dt;

                }

 

 

                /// <summary>  

                ///             Converts an array of objects into a data table.

                /// </summary>

                /// <param name="array">Specifies the array of objects that wil be used to create the data table.</param>

                /// <returns>Returns a data table created from the array of objects.</returns>

                public static DataTable ConvertToDataTable(Object[] array)

                {

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

                        DataTable dt = CreateDataTable(properties, null);

                        dt.TableName = array.GetType().GetElementType().Name;

 

                        if (array.Length != 0)

                        {

                                foreach(object source in array)

                                        FillData(properties, dt, null, String.Empty, source);

 

                        }

 

                        return dt;

                }

 

 

                /// <summary>

                ///             Creates a new data table from the properties of an object.

                /// </summary>

                /// <param name="properties">Specifies the property information used to create the data table.</param>

                /// <returns>Returns a data table created from an object.</returns>

                private static DataTable CreateDataTable(PropertyInfo[] properties, object source)

                {

                        DataTable dt = new DataTable();

                        CreateColumns(properties, dt, String.Empty, source);

                        return dt;

                }

 

 

                /// <summary>

                ///             Creates the columns in a data table from the properties of an object.

                /// </summary>

                /// <param name="properties">Specifies the property information used to create the columns.</param>

                /// <param name="dt">Specifies the data table being created.</param>

                /// <param name="expandedName">Specifies the property name plus the nested object's property name when the column name is from a nested object.</param>

                private static void CreateColumns(PropertyInfo[] properties, DataTable dt, String expandedName, object source)

                {

                        DataColumn dc = null;

                        PropertyInfo[] nestedProperties = null;

                        Object nested = null;

 

                        foreach(PropertyInfo pi in properties)

                        {                              

                                if (IsSystemType(pi.PropertyType.ToString()) || pi.PropertyType.IsEnum)

                                {

                                        dc = new DataColumn();

                                        dc.ColumnName = expandedName + pi.Name;

 

                                        if ( pi.PropertyType.IsEnum)    // Enums always get the string type because we stuff the enum item name as the value.

                                                dc.DataType = Type.GetType("System.String");

                                        else

                                                dc.DataType = pi.PropertyType;

                               

                                        dt.Columns.Add(dc);                            

                                }

                                else

                                {

                                        nested = pi.GetValue(source, null);

 

                                        if (pi.GetType().IsArray)

                                                nestedProperties = nested.GetType().GetElementType().GetProperties();

                                        else

                                                nestedProperties = nested.GetType().GetProperties();

                                       

                                        CreateColumns(nestedProperties, dt, pi.Name, nested);

                                }

                        }

                }

 

                /// <summary>

                ///             Fills a data row with values from an object.

                /// </summary>

                /// <param name="properties">Specifies the property that we are fill the data from.</param>

                /// <param name="dt">Specifies the data table being fllled.</param>

                /// <param name="row">Specifies the data row that will be filled with the property value.</param>

                /// <param name="expandedName">Specifies the property name plus the nested object's property name when the column name is from a nested object.</param>

                /// <param name="source">Specifies the object that contains the property being read..</param>

                private static void FillData(PropertyInfo[] properties, DataTable dt, DataRow row, String expandedName, object source)

                {

                        DataRow newRow = null;

                        PropertyInfo[] nestedProperties = null;

                        Object nested = null;

 

                        if (row == null)

                                newRow = dt.NewRow();

                        else

                                newRow = row;

 

                        foreach(PropertyInfo pi in properties)

                        {

                                if (IsSystemType(pi.PropertyType.ToString()) )

                                        newRow[expandedName + pi.Name] = pi.GetValue(source, null);

                                else if(pi.PropertyType.IsEnum)

                                {

                                        int i = 0;

                                        object itemVal = pi.GetValue(source, null);

                                        string[] names = Enum.GetNames(itemVal.GetType());                                                                                                             

 

                                        // Pull the enum text into the column value.

                                        foreach(object o in Enum.GetValues(itemVal.GetType()))

                                        {                                              

                                                if (o.ToString() == itemVal.ToString())

                                                        newRow[expandedName + pi.Name] = names[i];                                     

                                                i++;

                                        }

 

 

                                }

                                else

                                {

                                        nested = pi.GetValue(source, null);

 

                                        if (pi.GetType().IsArray)

                                                nestedProperties = nested.GetType().GetElementType().GetProperties();

                                        else

                                                nestedProperties = nested.GetType().GetProperties();

 

                                        FillData(nestedProperties, dt, newRow, pi.Name, nested);

                                }

 

                        }

 

                        if (row == null)

                                dt.Rows.Add(newRow);   

                }

 

 

                /// <summary>

                ///             IsSystemType determines if the name of a proerty type is one of the system data types.

                /// </summary>

                /// <param name="type">Specifies the name of the property type.</param>

                /// <returns>True if the type is a system type, otherwise false.</returns>

                private static bool IsSystemType(String type)

                {

                        String utype = type.ToUpper();

 

                        foreach(String st in _systemTypes)

                        {

                                if (utype == st)

                                        return true;

                        }

 

                        return false;

                }

 

 

 

        }

}



 

Comments

Javier Luna said:

I believe that any DataLayer must be a simple code block, that they allow operations against DB.

That code block would not have to know on the Business Entities. Single to specialize it is to execute the operations (Store Procedures and SQL Sentences) against the engine DB (SQL, Oracle, DB2, etc.), with which this setting.

Finally, I invite to you to download the DataLayer.Primitives Public Version.

This is very cool Data Layer :)

DataLayer.Primitives - Readme!
http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=1389

Cheers,

Javier Luna
http://guydotnetxmlwebservices.blogspot.com/
# May 26, 2005 11:18 PM

Josh said:

This class doesn't support any properties that are Nullable<>.

# October 12, 2007 5:28 AM

Ray said:

This article is great. Easy to modify to make it work with Nullable<>.

While checking for the SystemType, also check for Nullable<>.

if( IsNullableType( pi.PropertyType ) ) {

   type = type.GetGenericArguments()[0];

}

private static bool IsNullableType( Type theType ) {

  return ( theType.IsGenericType && theType.

           GetGenericTypeDefinition().Equals

           ( typeof( Nullable<> ) ) );

}

Filling the Dataset should be straight forward.

# January 9, 2009 3:58 PM

hc1 said:

I can't get this to work.  I have an array of an object.  The object is a class with 23 properties (string, bool and Guid).  The array has 560 rows.

I get "A column named 'SyncRootLength' already belongs to this DataTable" at dt.Columns.Add(dc).

So I modified the column name line to

dc.ColumnName = expandedName + pi.Name + Guid.NewGuid().ToString();

This result in a stack overflow, obviously from the recursive call to CreateColumns.  But is 560 elements really that large?

Thanks.

# July 30, 2010 3:47 AM

Online Geld Gewinnen said:

Also ich vermute das ist nur ne Modeerscheinung

# November 26, 2010 12:30 PM

Lottoziehung heute said:

Unglaublich! Sowas hätte ich gar nicht geglaubt :)        

# January 27, 2011 10:13 PM

Tagesgeld said:

Krass dass das tatsachlich wirklich funktioniert :-)          

# February 4, 2011 8:43 AM

Novoline Trick said:

Hat jemand eine Idee wie sehr dies verallgemeinerbar ist?

# February 7, 2011 9:27 AM

Knacken said:

Tjo, die Dinge können so trivial erscheinen. Besten Dank für die Erläuterungen ;)      

# February 8, 2011 5:52 PM

Book of Ra Tricks said:

Also ich vermute das war eh nur eine Mode    

# February 15, 2011 9:08 AM

Book of ra download said:

Nun ja, die Dinge können manchmal wirklich einfach sein. Danke ;-)    

# February 18, 2011 10:38 PM

Tricks said:

Krass, ich habe garnicht gedacht, dass dies in der Realität auch wirklich klappt      

# February 28, 2011 1:34 AM

cool said:

Hat irgendjemand eine Idee wie sehr das verallgemeinerbar ist?    

# February 28, 2011 4:51 PM

novoline said:

Wirklich ein super Beitrag. Ich söllte weblogs.asp.net mal mehr lesen :-)    

# April 3, 2011 10:00 PM

Home Security Monitoring system said:

naturally like your web-site but you need to check the spelling on quite a few of your posts. Several of them are rife with spelling problems and I find it very bothersome to tell the truth nevertheless I'll surely come back again.

<b><a href="www.blogsfirst.com/.../what-do-you-know-about-the-home-security-systems.html

">wireless Home Security Monitoring

<a/><b/>

# April 14, 2011 3:56 AM

football said:

Hello! I love watching football and I loved your blog as well.

# May 22, 2011 2:00 AM

Cheap Supra Footwear said:

I agree with your Blog and I will be back to check it more in the future so please keep up your work. I love your content & the way that you write. It looks like you have been doing this for a while now, how long have you been blogging for?

# July 23, 2011 12:48 AM

Monster beats studio said:

Do you have a spam problem on this site; I also am a blogger, and I was wanting to know your situation; many of us have created some nice practices and we are looking to swap solutions with others, be sure to shoot me an email if interested.<a href="www.cheapmonsterbeatsheadphones.com/" title="Monster beats studio">Monster beats studio</a>

# July 25, 2011 4:41 AM

authentic handbags said:

I learn something new on different blogs everyday. It is always refreshing to read posts of other blogger and learn something from them.<a href="www.2011handbagsoutlet.com/" title="authentic handbags">authentic handbags</a>

# July 25, 2011 4:46 AM

baseball caps said:

the style we mainly found was Stencil Graffiti Art as well plenty of Murals and other similar intensive artworks. Not just text and type. <a href="www.baseballcaps-forsale.com/" title="baseball caps">baseball caps</a>

# July 25, 2011 4:51 AM

buy nike air max said:

You managed to hit the nail upon the top as well asand alsoand defined out the whole thing without having side effectside-effects , people cancould take a signal. Will likelyprobably be back to get more. Thanks.<a href="www.buynike-airmax.com/" title="buy nike air max">buy nike air max</a>

# July 25, 2011 10:40 PM

burberry bags outlet said:

I like the quality paintings on the walls. I have posted a few also in my site.<a href="www.burberrybagsoutletsale.com/" title="burberry bags outlet">burberry bags outlet</a>

# July 26, 2011 3:55 AM

Gucci outlet store said:

very artistic look. And also, attractive design of these gloves. Then, I will also try to make like this, for my own use.<a href="www.buyguccioutlet.com/" title="Gucci outlet store">Gucci outlet store</a>

# July 26, 2011 5:10 AM

authentic handbags said:

I learn something new on different blogs everyday. It is always refreshing to read posts of other blogger and learn something from them.<a href="www.2011handbagsoutlet.com/" title="authentic handbags">authentic handbags</a>

# July 29, 2011 5:12 AM

Moncler jackets outlet said:

This site is very helpful and very informative for me. i am so glad to find out your blog immediately. thanks for sharing with us.<a href="www.jacketsmoncleroutlet.com/" title="Moncler jackets outlet">Moncler jackets outlet</a>

# August 1, 2011 2:44 AM

chanel outlet said:

You managed to hit the nail upon the top as well asand alsoand defined out the whole thing without having side effectside-effects , people cancould take a signal. Will likelyprobably be back to get more. Thanks<a href="www.authentic-chanel-outlet.com/" title="Chanel Outlet ">Chanel Outlet</a>

# August 3, 2011 3:10 AM

Timberland boots outlet said:

Very nice post. I really enjoy the reading. I  come here from the google while searching for some good article.Thanks <a href="www.cheap-timberlandbootsoutlet.com/" title="Timberland boots outlet">Timberland boots outlet</a>

# August 3, 2011 5:14 AM

discount gucci bags said:

Thanks a lot for enjoying this beauty article with me. I am enjoy it very much! Looking forward to another great article. Good luck to the author! all the best!<a href="www.discountguccibagssales.com/" title="discount gucci bags">discount gucci bags</a>

# August 3, 2011 11:47 PM

burberry bags outlet said:

This is a really good read for me, Must admit that you are one of the best bloggers I ever saw.Thanks for posting this informative article.<a href="www.burberrybagsoutletsale.com/" title="burberry bags outlet">burberry bags outlet</a>

# August 4, 2011 11:40 PM

Prada handbags outlet said:

This is a fantatic web site.  Good fresh interface and nice informative blogs. I will be coming back in a bit, thanks for the great blog.<a href="www.pradabagsoutletstore.com/" title="Prada handbags outlet">Prada handbags outlet</a>

# August 6, 2011 3:48 AM

Nike Shox cheap said:

This website has got lots of extremely helpful info on it. Thanks for helping me.<a href="www.nikeshoxcheapsale.com/" title="Nike Shox cheap">Nike Shox cheap</a>

# August 8, 2011 3:53 AM

The North Face Canada said:

Thanks very much for this wonderful blog;this is the kind of thing that keeps me going through the day.

# August 9, 2011 3:38 AM

cheap Burberry outlet said:

I never thought of this angle regarding this subject. Great post. I will bookmark it straightaway.<a href="www.cheap-burberryoutlet.com/" title="cheap Burberry outlet">cheap Burberry outlet</a>

# August 10, 2011 8:13 PM

chanel outlet said:

For I like your article, which I make their own evaluation. We provide <a href="www.authentic-chanel-outlet.com/" title="Chanel Outlet "> Chanel Outlet </ a>

# August 13, 2011 6:08 AM

Monster beats studio said:

I really loved reading your blog. It was very well authored and easy to undertand.

# August 15, 2011 9:43 PM

cheap north face jackets said:

I continue to read blogs like this, because I am trying to better my ability to write great content, this is an awesome example.[url=www.cheapnorthfaceoutlets.com]cheap north face jackets[/url]

# August 19, 2011 5:05 AM

rtyecript said:

I really liked the article, and the very cool blog

# August 23, 2011 1:16 AM

sac louis vuitton said:

Hey this is really nice information. I was looking for something similar like this. Thanks for this useful information.

# September 2, 2011 10:32 PM

Prada handbags outlet said:

Your blog is perfect, and I like this article. I find the information I need. I think I can find more useful information here, thanks.<a href="www.pradabagsoutletstore.com/" title="Prada handbags outlet">Prada handbags outlet</a> .

# September 5, 2011 3:30 AM

Abercrombie outlet sale said:

Just want to say your article is brilliant. The clarity in your post is simply impressive and i can assume you are an expert on this subject.

# September 8, 2011 9:14 PM

Ralph Lauren outlet said:

Thanks for sharing your thoughts with us.I enjoyed well while reading your article.<a href="www.ralphlaurenoutletstore.net/" title="Ralph Lauren outlet">Ralph Lauren outlet</a>

# September 9, 2011 5:15 AM

cheap prada handbags said:

I am glad to found such useful post. I really increased my knowledge after read your post which will be beneficial for me.<a href="www.cheappradahandbagsonline.com/" title="cheap prada handbags">cheap prada handbags</a>

# September 15, 2011 10:39 PM

Spielautomaten Tricks said:

Hat jemand ne Meinung wie stark das verallgemeinerbar ist?

# December 1, 2011 8:01 PM

Spielautomaten Trick said:

Ich bemerke gerade in diesem Moment  dass ich diesen Blog wesentlich haufiger aufrufen musste ;-) - da kommt man wirklich auf krasse Ideen                      

# December 4, 2011 10:03 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)