views:

1976

answers:

3

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?

+8  A: 

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)

Marc Gravell
When I grow up, I want to be Marc Gravell.
Ronnie Overby
Mmmm. Null-coalescing operator. So pretty.
J. Steen
@Ronnie - me too...
Marc Gravell
Thank you for pointing out that operator...
Daren Thomas
+2  A: 

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.

J. Steen
+2  A: 

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.

Anton Gogolev