Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET - Convert Generic Collection to DataTable

I am trying to convert a generic collection (List) to a DataTable. I found the following code to help me do this:

// Sorry about indentation
public class CollectionHelper
{
private CollectionHelper()
{
}

// this is the method I have been using
public static DataTable ConvertTo<T>(IList<T> list)
{
    DataTable table = CreateTable<T>();
    Type entityType = typeof(T);
    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entityType);

    foreach (T item in list)
    {
        DataRow row = table.NewRow();

        foreach (PropertyDescriptor prop in properties)
        {
            row[prop.Name] = prop.GetValue(item);
        }

        table.Rows.Add(row);
    }

    return table;
}    

public static DataTable CreateTable<T>()
{
    Type entityType = typeof(T);
    DataTable table = new DataTable(entityType.Name);
    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entityType);

    foreach (PropertyDescriptor prop in properties)
    {
        // HERE IS WHERE THE ERROR IS THROWN FOR NULLABLE TYPES
        table.Columns.Add(prop.Name, prop.PropertyType);
    }

    return table;
}
}

My problem is that when I change one of the properties of MySimpleClass to a nullable type, I get the following error:

DataSet does not support System.Nullable<>.

How can I do this with Nullable properties/fields in my class?

like image 313
Ronnie Overby Avatar asked Mar 31 '09 14:03

Ronnie Overby


3 Answers

Then presumably you'll need to lift them to the non-nullable form, using Nullable.GetUnderlyingType, and perhaps change a few null values to DbNull.Value...

Change the assignment to be:

row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;

and when adding the columns to be:

table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(
            prop.PropertyType) ?? prop.PropertyType);

And it works. (?? is the null-coalescing operator; it uses the first operand if it is non-null, else the second operand is evaluated and used)

like image 135
Marc Gravell Avatar answered Nov 05 '22 22:11

Marc Gravell


Well. Since DataSet does not support nullable types, you'd have to check if the property is a generic type, get the generic definition of that type and then get the argument (which is the actual type) using, perhaps, Nullable.GetUnderlyingType. If the value is null, just use DBNull.Value in the DataSet.

like image 24
J. Steen Avatar answered Nov 06 '22 00:11

J. Steen


If Nullable.GetUnderlyingType() given your prop.PropertyType returns a not-null value, use that as the type of a column. Otherwise, use prop.PropertyType itself.

like image 5
Anton Gogolev Avatar answered Nov 06 '22 00:11

Anton Gogolev