Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert DataTable to List<T>

I have a doubt, sometime I made this conversion from DataTable to List<T>:

  List<EDog> lstDogs = (from drRow in dsDogs.Tables[0].AsEnumerable()
                        select new EDog()
                        {
                            intIdDog = drRow.Field<int>("IdDog"),
                            intIdOwner = drRow.Field<int?>("IdOwner"),
                            intAge = drRow.Field<int>("Age"),
                            strName = drRow.Field<string>("Name")
                       }).ToList();

This worked fine, but now I'm thinking about doing it generic, so that any type of DataSet could be converted to a strongly typed list.

How could I make it generic? maybe a delegate surrounding this part and creating the object?

new EDog()
{
    intIdDog = drRow.Field<int>("IdDog"),
    intIdOwner = drRow.Field<int?>("IdOwner"),
    intAge = drRow.Field<int>("Age"),
    strName = drRow.Field<string>("Name")
}

I tried it but get an error:

select (lambda) expected....

Any suggestion?

The reason why I need this is because each DataRow of the result, needs to be converted to an Entity for better manipulation.

like image 949
lidermin Avatar asked Feb 17 '10 15:02

lidermin


People also ask

How to Convert DataTable to ArrayList in c#?

ArrayList rows = new ArrayList(); foreach (DataRow dataRow in myDataTable. Rows) rows. Add(string. Join(";", dataRow.


1 Answers

Ok, let's have some fun:

public static class DataTableExtensions
{
    public static List<T> ToGenericList<T>(this DataTable datatable, Func<DataRow, T> converter)
    {
        return (from row in datatable.AsEnumerable()
                select converter(row)).ToList();
    }
}

class EDog
{
    private int intIdDog;
    private int intIdOwner;
    private int intAge;
    private string strName;

    ...

    public static EDog Converter(DataRow row)
    {
        return new EDog
                        {
                            intIdDog = (int)row["IdDog"],
                            intIdOwner = (int)row["IdOwner"],
                            intAge = (int)row["Age"],
                            strName = row["Name"] as string
                        };
    }
}

Usage:

List<EDog> dogs = dsDogs.Tables[0].ToGenericList<EDog>(EDog.Converter);

But there is not enough fun, right? What about this:

class DataRowKeyAttribute : Attribute
{
    private readonly string _Key;

    public string Key
    {
        get { return _Key; }
    }

    public DataRowKeyAttribute(string key)
    {
        _Key = key;
    }
}


static class DataTableExtensions
{
    public static List<T> ToGenericList<T>(this DataTable datatable) where T : new()
    {
        return (from row in datatable.AsEnumerable()
                select Convert<T>(row)).ToList();
    }

    private static T Convert<T>(DataRow row) where T : new()
    {
        var result = new T();

        var type = result.GetType();

        foreach (var fieldInfo in type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
        {
            var dataRowKeyAttribute = fieldInfo.GetCustomAttributes(typeof (DataRowKeyAttribute), true).FirstOrDefault() as DataRowKeyAttribute;
            if (dataRowKeyAttribute != null)
            {
                fieldInfo.SetValue(result, row[dataRowKeyAttribute.Key]);
            }
        } 

        return result;
    }
}

class EDog
{
    [DataRowKey("IdDog")]
    private int intIdDog;
    [DataRowKey("IdOwner")]
    private int intIdOwner;
    [DataRowKey("Age")]
    private int intAge;
    [DataRowKey("Name")]
    private string strName;

    ... 
}

Usage:

List<EDog> dogs = dsDogs.Tables[0].ToGenericList<EDog>();

And if you want to have REAL fun, add error handling, consider caching reflection data to improve performance and changing fields to properties.

like image 139
bniwredyc Avatar answered Sep 23 '22 22:09

bniwredyc