Search code examples
c#linqanonymous-typessystem.data.datatable

Create a sequence of anonymous types from the rows in a DataTable


This is a "let's see if it can be done" exercise more than anything else.

Suppose I have a DataTable with several columns. Using linq, is it possible to select the rows of the table such that the result will be a sequence of an anonymous type where each property of the anonymous type is named according to the column name of the DataTable and the type of each property is set appropriately.

So if my DataTable has three columns like so:

Name = "Column1",  DataType = string
Name = "Column2",  DataType = integer
Name = "Column3",  DataType = bool

Then I want to select all the rows of the DataTable such that the anonymous type has three properties:

DataSet ds = functionThatGetsADataSet();
var seq = ds.Tables[0].AsEnumerable().Select( r => **** MAGIC HERE ****)

foreach (var s in seq)
{
    Console.WriteLine(s.Column1);
    Console.WriteLine(s.Column2);
    Console.WriteLine(s.Column3);
}

I know that I can do this:

DataSet ds = functionThatGetsADataSet();
var seq = ds.Tables[0].AsEnumerable().Select( r => 
   new 
   {
       Column1 = r.Field<string>("Column1"),
       Column2 = r.Field<int>("Column2"),
       Column3 = r.Field<bool>("Column3"),
   }
)

foreach (var s in seq)
{
    Console.WriteLine(s.Column1);
    Console.WriteLine(s.Column2);
    Console.WriteLine(s.Column3);
}

but this requires hard coding the property names in the new clause, whereas I would like the property names to come from the Columns collection of the DataTable.

I hope that I have explained this clearly enough. After playing around with this for a little bit, I am beginning to think that anything that I come up with will be a big mess as far as readability and maintainability goes, but I thought I would ask.


Solution

  • I'm afraid that there is no such magic (at least not with anonymous types). Anonymous types are implicit types generated by the compiler as immutable classes with their properties named & typed by the explicit assignment operation like in your second example (at compile time).

    What you're wanting to do would require a dynamic type constructed at run time.