Monday, January 28, 2008 11:54 AM monkey9987

LINQ to DataTable

We have been adopting Linq slowly but surely and have run into some issues we never had to deal with in the past.  Currently I use DataSets in VS2005 for everything.  These are nice since they return DataTables easily and allow updates / inserts / etc without issue. 

When we dove into Linq and had to return a DataTable for the first time we were stuck.  Looking through examples & searching online did not return much. I did find an example by Kevin Goff in CoDe Magazine which outlined 13 tips for Linq.  This worked great except I had some issues with null datatypes. Those issues should be fixed in the sample below.

The following code outlines a quick way using Linq to query a database and return the results to a DataTable.

Here is my newly created class:

static public class ConvertDataTable

{

public static DataTable ToADOTable<T>(this IEnumerable<T> varlist, CreateRowDelegate<T> fn)

{

DataTable dtReturn = new DataTable();

// Could add a check to verify that there is an element 0

T TopRec = varlist.ElementAt(0);

// Use reflection to get property names, to create table

// column names

PropertyInfo[] oProps =

((Type)TopRec.GetType()).GetProperties();

foreach (PropertyInfo pi in oProps)

{

Type colType = pi.PropertyType;if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))

{

colType = colType.GetGenericArguments()[0];

}

dtReturn.Columns.Add(
new DataColumn(pi.Name, colType));

}

foreach (T rec in varlist)

{

DataRow dr = dtReturn.NewRow();foreach (PropertyInfo pi in oProps)
{
   dr[pi.Name] = pi.GetValue(rec,
null) == null ? DBNull.Value : pi.GetValue(rec, null);
}

dtReturn.Rows.Add(dr);

}

return (dtReturn);

}

public delegate object[] CreateRowDelegate<T>(T t);

}

Here is the usage in code:

LData.MyDataContext db = new LData.MyDataContext();
var query = from p in db.Extensions
w
here p.DepartmentNumber == "412"select p;

DataTable dt = query.ToADOTable(rec => new object[] { query });

 

Hope this helps someone else out.

~ Steve

 

Filed under: , ,

Comments

# re: LINQ to DataTable

Monday, January 28, 2008 5:10 PM by Fabrice Marguerie

See Andrew Conrad's code: blogs.msdn.com/.../science-project.aspx

A VB version can be found here: blogs.msdn.com/.../pathetic-plea-for-help.aspx

We also have C# and VB versions of this source code in the samples' source code of the LINQ in Action book (http://LinqInAction.net).

Here is the complete archive: linqinaction.net/.../entry1952.aspx

See the files DataSetLinqOperators.vb and ObjectShreder.vb in Chapter14.VB\Chapter14.

Note: In our version, we kept the original names of the query operators for clarity (ToDataTable and LoadSequence).

# Link Listing - January 28, 2008

Monday, January 28, 2008 11:17 PM by Christopher Steen

Link Listing - January 28, 2008

# Link Listing - January 28, 2008

Monday, January 28, 2008 11:18 PM by Christopher Steen

WPF How can I debug WPF bindings? [Via: Bea ] Code Camps South Florida Code Camp this weekend [Via:...

# re: LINQ to DataTable

Sunday, February 10, 2008 2:57 AM by Pradeep Mishra

Here is the changed code, coz above code will run into error..IENUMERABLE varlist can not be enumerated more than once

public static class ConvertDataTable

   {

       public static DataTable ToADOTable<T>(this IEnumerable<T> varlist, CreateRowDelegate<T> fn)

       {

           DataTable dtReturn = new DataTable();

           // column names

           PropertyInfo[] oProps = null;

           // Could add a check to verify that there is an element 0

           foreach (T rec in varlist)

           {

               // Use reflection to get property names, to create table, Only first time, others will follow

               if (oProps == null)

               {

                   oProps = ((Type)rec.GetType()).GetProperties();

                   foreach (PropertyInfo pi in oProps)

                   {

                       Type colType = pi.PropertyType; if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))

                       {

                           colType = colType.GetGenericArguments()[0];

                       }

                       dtReturn.Columns.Add(new DataColumn(pi.Name, colType));

                   }

               }

               DataRow dr = dtReturn.NewRow(); foreach (PropertyInfo pi in oProps)

               {

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

               }

               dtReturn.Rows.Add(dr);

           }

           return (dtReturn);

       }

       public delegate object[] CreateRowDelegate<T>(T t);

   }

# re: LINQ to DataTable

Thursday, February 28, 2008 8:13 AM by Thomas

Thanks Steve.  

I was looking for something clean that does just this.  

# re: LINQ to DataTable

Tuesday, April 22, 2008 11:55 AM by Mark Kamoski

Can you give a brief sample of how this is called?

# re: LINQ to DataTable

Tuesday, April 29, 2008 9:47 AM by monkey9987

Mark,

There's an example listed above on how to use it:

1. Create your data context

LData.MyDataContext db = new LData.MyDataContext();

2. Generate your query

var query = from p in db.Extensions

where p.DepartmentNumber == "412"select p;

3. Convert the result to a datatable

DataTable dt = query.ToADOTable(rec => new object[] { query });

Let me know if that works for you or not.

~ Steve

# re: LINQ to DataTable

Tuesday, May 06, 2008 11:18 AM by James

What if my datacontext is a datatable instead of a database? I have to append the asEnumerable()  method  to the datatable in the linq statement so that it doesn't throw an error on build.

The results contain rowerrors and fail.

# re: LINQ to DataTable

Wednesday, June 18, 2008 1:40 PM by JoshRoss

Module ConvertDataTable

<System.Runtime.CompilerServices.Extension()> _

Public Function ToDataTable(Of T)(ByVal value As IEnumerable(Of T)) As DataTable

 Dim returnTable As New DataTable

 Dim firstRecord = value.First

 For Each pi In firstRecord.GetType.GetProperties

  returnTable.Columns.Add(pi.Name, pi.GetValue(firstRecord, Nothing).GetType)

 Next

 For Each result In value

  Dim nr = returnTable.NewRow

  For Each pi In result.GetType.GetProperties

   nr(pi.Name) = pi.GetValue(result, Nothing)

  Next

  returnTable.Rows.Add(nr)

 Next

 Return returnTable

End Function

End Module

# re: LINQ to DataTable

Friday, July 11, 2008 2:11 PM by Mark Kamoski

I am getting a CTE of...

Error 1 The non-generic type 'System.Collections.IEnumerable' cannot be used with type arguments C:\Code\Team\Clear\Web\App_Code\Business\Components\ConvertDataTable.cs 20 45 C:\...\Web\

...when I try to compile...

...my using statements are...

using System;

using System.Data;

using System.Collections;

using System.Configuration;

using System.Linq;

using System.Linq.Expressions;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml;

using System.Xml.Linq;

...and the class is exactly as you pasted it above.

Ideas?

Thank you.

-- Mark Kamoski

# re: LINQ to DataTable

Friday, July 11, 2008 4:00 PM by Mark Kamoski

These using statements work...

using System;

using System.Data;

using System.Collections;

using System.Collections.Generic;

using System.Collections.ObjectModel;

using System.Collections.Specialized;

using System.Configuration;

using System.Linq;

using System.Reflection;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

# re: LINQ to DataTable

Tuesday, July 29, 2008 5:49 PM by caseywills

awesome man. saved me a ton of work!

# re: LINQ to DataTable

Wednesday, September 17, 2008 8:17 PM by Adam

You Rock!  Code works great, and saved me a lot of heart ache!

# re: LINQ to DataTable

Tuesday, September 30, 2008 7:17 AM by Holf

This is just fantastic. For ASP.NET stuff when you want to bind to tabular information it is just perfect.

Thanks!

# re: LINQ to DataTable

Tuesday, October 07, 2008 2:18 AM by Kim

Thats great!

# re: LINQ to DataTable

Monday, November 03, 2008 11:14 PM by Hang Ta

It's help me resolved my problem.

thanks

Leave a Comment

(required) 
(required) 
(optional)
(required)