davy
davy

Reputation: 4562

Using GetField<T> to set values in an object from a DataRow

I'm trying to write a generic method to return values from columns in a DataRow.

    protected static T GetField<T>(DataRow row, string name, T defaultValue)
    {
        if (row == null)
        {
            throw new ArgumentNullException("row");
        }

        T result = defaultValue;
        if (row.Table.Columns.Contains(name) && !row.IsNull(name))
        {                
            result = row.Field<T>(name);
        }
        return result;
    }

When trying to assign values to specific tests I get 'Specified cast is not valid.' exception.

var rule = new MyObj
{                   
    AString = GetField(row, "AnswerId", "test"),
    AnInt  = GetField(row, "Decline", 0),
    ADecimal = GetField(row, "LoadFactor", 1M),                                     
};

I'm trying to avoid writing an overload for each type.

Can this be done?

Upvotes: 0

Views: 970

Answers (1)

Ehsan Sajjad
Ehsan Sajjad

Reputation: 62498

You can use these extension Methods to convert whole DataTable to List, instead of writing method for DataRow:

public static class DataTableExtensions
    {
        public static List<T> ToList<T>(this DataTable table) where T : new()
        {
            List<PropertyInfo> properties = typeof(T).GetProperties().ToList();
            List<T> result = new List<T>();

            foreach (var row in table.Rows)
            {
                var item = CreateItemFromRow<T>((DataRow)row, properties);
                result.Add(item);
            }

            return result;
        }

        private static T CreateItemFromRow<T>(DataRow row, List<PropertyInfo> properties) where T : new()
        {
            T item = new T();
            foreach (var property in properties)
            {
                if (row.Table.Columns.Contains(property.Name))
                {
                    if (row[property.Name] != DBNull.Value)
                        property.SetValue(item, row[property.Name], null);
                }
            }
            return item;
        }
    }

and use it like this:

List<SomeType> list = SomeDataTable.ToList<SomeType>();

But you have to make sure that name of columns that are selected in query should match the class properties and datatypes should also match.

Upvotes: 1

Related Questions