简体   繁体   中英

Convert datatable to list of generic type

How to convert datatable into list of generic type. Below is the scenario. I have datatable with name table1 and contains columns col1,col2 . how could we convert this table into a list of type name table1bj (which can be different per the datatable name) with properties col1 and col2 with compatible datatype as of datatable column data types.

There are many post on SO but these are with the converting datatable into predefined object list. Here in my case I have to generate object and list dynamically from the datatable. Thanks.

Assuming that you've already created the class table1bj (consider to make it uppercase due to .NET naming conventions) with two properties col1 , col2 (the same). You just have to use Enumerable.Select to create instances of this class and ToList to create a generic List<table1bj> :

List<table1bj> result = table1.AsEnumerable()
    .Select(row => new table1bj 
                       { 
                           col1 = row.Field<string>("col1"), 
                           col1 = row.Field<string>("col1") 
                       }
    ).ToList();

I have also presumed that these properties are string s, otherwise use the correct type with the Field extension method. If you don't know the type you should stay with your DataTable since it's already an in-memory collection with dynamic types.

You can do like this...

Create Class with properties :

public class table1bj
    {
        public string col1{ get; set; }
        public string col2{ get; set; }
    }

Convert DataTable to Generic Type :

List<table1bj> Objtable1bj = table1.ToCollection<table1bj>();

I know this question asked many times ago, but also I need a solutions for convert data table to dynamic or generic types in one method and I can't find answer for this, so post my answer.

You can use a extension method to convert data table to any type like below:

public static class Extension
{
    public static IList<T> ToList<T>(this DataTable dt, bool isFirstRowColumnsHeader = false) where T : new()
    {
        var results = new List<T>();

        if (dt != null && dt.Rows.Count > 0)
        {
            var columns = dt.Columns.Cast<DataColumn>().ToList();
            var rows = dt.Rows.Cast<DataRow>().ToList();
            var headerNames = columns.Select(col => col.ColumnName).ToList();
            //
            // Find properties name or columns name
            if (isFirstRowColumnsHeader)
            {
                for (var i = 0; i < headerNames.Count; i++)
                {
                    if (rows[0][i] != DBNull.Value && !string.IsNullOrEmpty(rows[0][i].ToString()))
                        headerNames[i] = rows[0][i].ToString();
                }

                //
                // remove first row because that is header
                rows.RemoveAt(0);
            }

            // Create dynamic or anonymous object for `T type
            if (typeof(T) == typeof(System.Dynamic.ExpandoObject) ||
                typeof(T) == typeof(System.Dynamic.DynamicObject) ||
                typeof(T) == typeof(System.Object))
            {
                var dynamicDt = new List<dynamic>();
                foreach (var row in rows)
                {
                    dynamic dyn = new ExpandoObject();
                    dynamicDt.Add(dyn);
                    for (var i = 0; i < columns.Count; i++)
                    {
                        var dic = (IDictionary<string, object>)dyn;
                        dic[headerNames[i]] = row[columns[i]];
                    }
                }
                return (dynamic)dynamicDt;
            }
            else // other types of `T
            {
                var properties = typeof(T).GetProperties();
                if (columns.Any() && properties.Any())
                {
                    foreach (var row in rows)
                    {
                        var entity = new T();
                        for (var i = 0; i < columns.Count; i++)
                        {
                            if (!row.IsNull(columns[i]))
                            {
                                typeof(T).GetProperty(headerNames[i])? // ? -> maybe the property by name `headerNames[i]` is not exist in entity then get null!
                                    .SetValue(entity, row[columns[i]] == DBNull.Value ? null : row[columns[i]]);
                            }
                        }
                        results.Add(entity);
                    }
                }
            }
        }
        return results;
    }

}

We can do it by Reflection also, this method helps to set ClassObject properties by DataTable:

    using System.Reflection;

    public void SetObjectProperties(object objClass, DataTable dataTable)
    {
        DataRow _dataRow = dataTable.Rows[0];
        Type objType = objClass.GetType();
        List<PropertyInfo> propertyList = new List<PropertyInfo>(objType.GetProperties());

        foreach (DataColumn dc in _dataRow.Table.Columns)
        {
            var _prop = propertyList.Where(a => a.Name == dc.ColumnName).Select(a => a).FirstOrDefault();

            if (_prop == null) continue;

            _prop.SetValue(objClass, Convert.ChangeType(_dataRow[dc], Nullable.GetUnderlyingType(_prop.PropertyType) ?? _prop.PropertyType), null);
        }
    }

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