【问题标题】:Convert datatable to list of generic type将数据表转换为泛型列表
【发布时间】:2013-12-13 08:53:10
【问题描述】:

如何将数据表转换为泛型列表。下面是场景。 我有名称为table1 的数据表并包含列col1,col2我们如何将此表转换为类型名称 table1bj(根据数据表名称可能不同)的列表,其中 col1 和 col2 属性具有与数据表列数据类型兼容的数据类型。

有很多关于 SO 的帖子,但这些都是将数据表转换为预定义的对象列表。在我的例子中,我必须从数据表中动态生成对象和列表。谢谢。

【问题讨论】:

  • 为什么不用实体框架?
  • 您能告诉我们您是如何填充数据表的吗?用户输入?绑定到一个集合?
  • @DaveRook :我们正在使用 wcf 服务进行数据访问层
  • @eraj,WCF 数据服务和 EF 可以很好地结合在一起。
  • @Tim 答案是正确的,这里唯一的说明是-考虑直接从数据库中获取table1bj 的集合,而不填充中间数据表

标签: c# .net linq datatable


【解决方案1】:

假设您已经创建了具有两个属性 col1col2(相同)的类 table1bj(由于 .NET 命名约定,请考虑将其设为大写)。你只需要使用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();

我还假设这些属性是strings,否则使用Field扩展方法的正确类型。如果您不知道类型,您应该使用 DataTable,因为它已经是具有动态类型的内存集合。

【讨论】:

  • @Time Schmelter:请注意,我不知道 table1obj 及其列。这也应该从数据表定义动态创建
  • @eraj:那么你不能使用一个类,也许是一个匿名类。但是未知类违反了泛型列表的原则,所以还是用DataTable吧。
【解决方案2】:

你可以这样做......

使用属性创建类:

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

将 DataTable 转换为通用类型:

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

【讨论】:

  • 可以参考ToCollection&lt;T&gt;的方法说明吗?
  • @Sangram:但它不是框架的一部分,因此您应该将其发布在答案本身而不是评论中的链接中。除此之外,您不能将DataRow 转换为table1bj
  • @Vishal : 我想将数据表转换为应动态生成的未知类型列表。
  • @eraj 这个博客可能对你有帮助...http://stackoverflow.com/questions/11787972/how-do-i-use-reflection-to-properly-cast-an-unknown-property-to-a-generic-list-t
【解决方案3】:

我知道这个问题问过很多次了,但我也需要一种解决方案,以一种方法将数据表转换为动态或泛型类型,但我找不到答案,所以发布我的答案。

您可以使用扩展方法将数据表转换为任何类型,如下所示:

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

}

【讨论】:

    【解决方案4】:

    我们也可以通过Reflection来实现,这个方法有助于通过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);
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 2021-03-28
      相关资源
      最近更新 更多