Is there a nice way to convert an IEnumerable to a DataTable?
I could use reflection to get the properties and the values, but that seems a bit inefficient, is there something build-in?
(I know the examples like: ObtainDataTableFromIEnumerable)
EDIT:
This question notified me of a problem handling null values.
The code I wrote below handles the null values properly.
public static DataTable ToDataTable<T>(this IEnumerable<T> items) {
// Create the result table, and gather all properties of a T
DataTable table = new DataTable(typeof(T).Name);
PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
// Add the properties as columns to the datatable
foreach (var prop in props) {
Type propType = prop.PropertyType;
// Is it a nullable type? Get the underlying type
if (propType.IsGenericType && propType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
propType = new NullableConverter(propType).UnderlyingType;
table.Columns.Add(prop.Name, propType);
}
// Add the property values per T as rows to the datatable
foreach (var item in items) {
var values = new object[props.Length];
for (var i = 0; i < props.Length; i++)
values[i] = props[i].GetValue(item, null);
table.Rows.Add(values);
}
return table;
}
I also came across this problem. In my case, I didn't know the type of the IEnumerable. So the answers given above wont work. However, I solved it like this:
Keep in mind that using this method, requires at least one item in the IEnumerable. If that's not the case, the DataTable wont create any columns.
I solve this problem by adding extension method to IEnumerable.
There is nothing built in afaik, but building it yourself should be easy. I would do as you suggest and use reflection to obtain the properties and use them to create the columns of the table. Then I would step through each item in the IEnumerable and create a row for each. The only caveat is if your collection contains items of several types (say Person and Animal) then they may not have the same properties. But if you need to check for it depends on your use.
I've written a library to handle this for me. It's called DataTableProxy and is available as a NuGet package. Code and documentation is on Github
To all:
Note that the accepted answer has a bug in it relating to nullable types and the DataTable. The fix is available at the linked site (http://www.chinhdo.com/20090402/convert-list-to-datatable/) or in my modified code below:
Note that both of these example are NOT extension methods like the example above.
Lastly... apologies for my extensive/excessive comments (I had a anal/mean prof that beat it into me! ;)
Firstly you need to add a
where T:class
constraint - you can't callGetValue
on value types unless they're passed byref
.Secondly
GetValue
is very slow and gets called a lot.To get round this we can create a delegate and call that instead:
The problem is that we don't know
TProperty
, but as usual on here Jon Skeet has the answer - we can use reflection to retrieve the getter delegate, but once we have it we don't need to reflect again:So now your method becomes:
You could further optimise it by storing the getters for each type in a static dictionary, then you will only have the reflection overhead once for each type.