简体   繁体   English

将数据表转换为通用类型列表

[英]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 . 我有名称为table1col1,col2并且包含列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. 我们如何将该表转换为类型名称为table1bj的列表(每个数据表名称可以不同),其属性为col1和col2,且数据类型与datatable列数据类型兼容。

There are many post on SO but these are with the converting datatable into predefined object list. SO上有很多文章,但是这些都是与将数据表转换为预定义的对象列表有关的。 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). 假设您已经创建了具有两个属性col1col2 (相同)的class table1bj (由于.NET命名约定,考虑使其变为大写)。 You just have to use Enumerable.Select to create instances of this class and ToList to create a generic List<table1bj> : 您只需要使用Enumerable.Select来创建此类的实例,并使用ToList来创建通用的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. 我还假定这些属性是string ,否则,请使用Field扩展方法使用正确的类型。 If you don't know the type you should stay with your DataTable since it's already an in-memory collection with dynamic types. 如果您不知道类型,则应该将其保留在DataTable因为它已经是具有动态类型的内存中集合。

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 : 将DataTable转换为泛型类型:

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: 我们也可以通过反射来做到这一点,该方法有助于通过DataTable设置ClassObject属性:

    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);
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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