简体   繁体   中英

How to convert IEnumerable<T> list to Datatable in C#

I am stuck with the following problem:

I normally use the function below to transfer custom data to DataTable but in this case the input data is a class composed of lists. I just need to write in DataTable the first element of each list per row. Could you help me to adjust this function in order to achieve this?

public List<int> xID { get; set; }
public List<string> xName { get; set; }
public List<string> xType { get; set; }
public List<string> xSource { get; set; }
public List<int> xmdID { get; set; }
public List<string> xMDName { get; set; }
public List<string> xUser { get; set; }

public static DataTable ListToDataTable<T>(IEnumerable<T> list)
{
    Type type = typeof(T);
    var properties = type.GetProperties();

    DataTable dataTable = new DataTable();
    foreach (PropertyInfo info in properties)
    {
        dataTable.Columns.Add(new DataColumn(info.Name, info.PropertyType));
    }

    foreach (T entity in list)
    {
        object[] values = new object[properties.Length];
        for (int i = 0; i < properties.Length; i++)
        {
            values[i] = properties[i].GetValue(entity);
        }

        dataTable.Rows.Add(values);
    }

    return dataTable;
}

Based in Carra answer I tried the code below but it did not recognize pType type (The type or namespace name 'pType' could not be found (are you missing a using directive or an assembly reference?))

var v = properties[i].GetValue(entity);
Type pType = properties[i].PropertyType;

if (pType.IsGenericType && pType.GetGenericTypeDefinition() == typeof(Nullable<>))
pType = Nullable.GetUnderlyingType(pType);

                if (pType.IsEnum)
                    pType = Enum.GetUnderlyingType(pType);

                if (v.GetType().GetGenericTypeDefinition() == typeof(List<>))
                {
                    values[i] = (v as List<pType>).First();
                }

UPDATE

I guess it is not the best solution because it does not accept any List type but it is the best I could do:

    public static DataTable ListToDataTable<T>(IEnumerable<T> list)
    {
        Type type = typeof(T);
        var properties = type.GetProperties();

        DataTable dataTable = new DataTable();
        foreach (PropertyInfo info in properties)
        {
            Type propertyType = info.PropertyType;

            if (propertyType.IsGenericType | propertyType.GetGenericTypeDefinition() == typeof(Nullable<>) | propertyType.IsEnum)
                propertyType = propertyType.GetGenericArguments()[0];

            dataTable.Columns.Add(new DataColumn(info.Name, propertyType));
        }

        foreach (T entity in list)
        {
            object[] values = new object[properties.Length];
            for (int i = 0; i < properties.Length; i++)
            {
                var v = properties[i].GetValue(entity);
                Type pType = v.GetType().GetGenericArguments().FirstOrDefault();

                if (v.GetType().GetGenericTypeDefinition() == typeof(List<>))
                {
                    if(pType == typeof(int))
                        values[i] = (v as List<int>).First();
                    else if(pType == typeof(string))
                        values[i] = (v as List<string>).First();
                }
                else
                {
                    values[i] = v;
                }
            }
            dataTable.Rows.Add(values);
        }
        return dataTable;
    }

You need something like this:

foreach (PropertyInfo info in properties)
{
    if(info.PropertyType == typeof(IEnumerable))
    {
       dataTable.Columns.Add(new DataColumn(info.Name, info.Cast<object>().First().GetType());
    }
    else
    {
       dataTable.Columns.Add(new DataColumn(info.Name, info.PropertyType));
    }
}

foreach (T entity in list)
{
    object[] values = new object[properties.Length];
    for (int i = 0; i < properties.Length; i++)
    {
        var v = properties[i].GetValue(entity);
        if(v is IEnumerable)
        {
          values[i] = (v.Cast<object>().First()).First();
        }
        else
        {
          values[i] = v;
        }
    }

    dataTable.Rows.Add(values);
}

This works for me. I got it here and modified it a little bit.

public static DataTable ToDataTable<T>(this System.Collections.Generic.List<T> collection, string _sTableName) {
        var table = new DataTable(_sTableName);
        var type = typeof(T);
        var properties = type.GetProperties();

        //Create the columns in the DataTable
        foreach (var property in properties) {
            if (property.PropertyType == typeof(int?)) {
                table.Columns.Add(property.Name, typeof(int));
            } else if (property.PropertyType == typeof(decimal?)) {
                table.Columns.Add(property.Name, typeof(decimal));
            } else if (property.PropertyType == typeof(double?)) {
                table.Columns.Add(property.Name, typeof(double));
            } else if (property.PropertyType == typeof(DateTime?)) {
                table.Columns.Add(property.Name, typeof(DateTime));
            } else if (property.PropertyType == typeof(Guid?)) {
                table.Columns.Add(property.Name, typeof(Guid));
            } else if (property.PropertyType == typeof(bool?)) {
                table.Columns.Add(property.Name, typeof(bool));
            } else {
                table.Columns.Add(property.Name, property.PropertyType);
            }
        }

        //Populate the table
        foreach (var item in collection) {
            var row = table.NewRow();
            row.BeginEdit();
            foreach (var property in properties) {
                row[property.Name] = property.GetValue(item, null) ?? DBNull.Value;
            }

            row.EndEdit();
            table.Rows.Add(row);
        }

        return table;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM