前言

DataTable是断开式的数据集合,所以一旦从数据库获取,就会在内存中创建一个数据的副本,以便使用。由于在实际项目中,经常会将DataTable中的每行数据转换为Model,然后放到List集合中,所以,下面提供了转换的两种思路:非泛型转换思路和泛型转换思路。

非泛型方式

首先来说下非泛型转换,这种转换方式就是通过遍历DataTable,然后向Model中的相同字段中赋值即可。

 //使用Linq的ToList方法,非泛型
        public static List<Entity> ConvertTo(DataTable dt)
        {
            if (dt == null) return null;
            if (dt.Rows.Count <= 0) return null;
 
            List<Entity> list = new List<Entity>();
            list = (from DataRow dr in dt.Rows
                    select new Entity
                    {
                        PID = Int32.Parse(dr["PID"].ToString()),
                        PName = dr["PName"].ToString(),
                        PPass = dr["PPass"].ToString(),
                        PAddr = dr["PAddr"].ToString()
                    }).ToList();
            return list;
        }

代码很简单,就是通过循环赋值而已。这里我用的Model测试类如下:

 
namespace DataSetToEntity.Code
{
    public class Entity
    {
        public int PID { get; set; }
 
        public string PName { get; set; }
 
        public string PPass { get; set; }
 
        public string PAddr { get; set; }
    }
}

泛型方式

然后,由于非泛型的版本不具有通用性,所以这里我们准备用泛型版本来实现一下,由于泛型版本是不可预知Model中的属性结构的,所以这里我们需要引入反射来进行操作。

//使用反射的泛型方法一
        public static List<T> ConvertTo<T>(DataTable dt) where T : new()
        {
            if (dt == null) return null;
            if (dt.Rows.Count <= 0) return null;
 
            List<T> list = new List<T>();
            try
            {
                List<string> columnsName = new List<string>();  
                foreach (DataColumn dataColumn in dt.Columns)
                {
                    columnsName.Add(dataColumn.ColumnName);//得到所有的表头
                }
                list = dt.AsEnumerable().ToList().ConvertAll<T>(row => getObject<T>(row, columnsName));  //转换
                return list;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
 
        public static T getObject<T>(DataRow row, List<string> columnsName) where T : new()
        {
            T obj = new T();
            try
            {
                string columnname = "";
                string value = "";
                PropertyInfo[] Properties = typeof(T).GetProperties();
                foreach (PropertyInfo objProperty in Properties)  //遍历T的属性
                {
                    columnname = columnsName.Find(name => name.ToLower() == objProperty.Name.ToLower()); //寻找可以匹配的表头名称
                    if (!string.IsNullOrEmpty(columnname))
                    {
                        value = row[columnname].ToString();
                        if (!string.IsNullOrEmpty(value))
                        {
                            if (Nullable.GetUnderlyingType(objProperty.PropertyType) != null) //存在匹配的表头
                            {
                                value = row[columnname].ToString().Replace("$", "").Replace(",", ""); //从dataRow中提取数据
                                objProperty.SetValue(obj, Convert.ChangeType(value, Type.GetType(Nullable.GetUnderlyingType(objProperty.PropertyType).ToString())), null); //赋值操作
                            }
                            else
                            {
                                value = row[columnname].ToString().Replace("%", ""); //存在匹配的表头
                                objProperty.SetValue(obj, Convert.ChangeType(value, Type.GetType(objProperty.PropertyType.ToString())), null);//赋值操作
                            }
                        }
                    }
                }
                return obj;
            }
            catch
            {
                return obj;
            }
        }
 
上面主要是通过反射获取T的属性名称,然后和DataRow中的表头相匹配,如果匹配的上,就赋值。下面是其简化版本:
 
//使用反射的泛型方法二
        public static List<T> ConvertToEx<T>(DataTable dt) where T : new()
        {
            if (dt == null) return null;
            if (dt.Rows.Count <= 0) return null;
 
            List<T> list = new List<T>();
            Type type = typeof(T);
            PropertyInfo[] propertyInfos = type.GetProperties();  //获取泛型的属性
            List<DataColumn> listColumns = dt.Columns.Cast<DataColumn>().ToList();  //获取数据集的表头,以便于匹配
            T t;
            foreach (DataRow dr in dt.Rows)   
            {
                t = new T();
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    try
                    {
                        DataColumn dColumn = listColumns.Find(name => name.ToString().ToUpper() == propertyInfo.Name.ToUpper());  //查看是否存在对应的列名
                        if (dColumn != null)
                            propertyInfo.SetValue(t, dr[propertyInfo.Name], null);  //赋值
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(ex.Message);
                    }
                }
                list.Add(t);
            }
            return list;
        }
 
至于使用方式,很简单,直接利用下面的代码即可:
 List<Entity> list = CommonUtils.ConvertToEx<Entity>(dt);



DataTable数据集转换为List非泛型以及泛型方式的更多相关文章

  1. C#高级语法之泛型、泛型约束,类型安全、逆变和协变(思想原理)

    一.为什么使用泛型? 泛型其实就是一个不确定的类型,可以用在类和方法上,泛型在声明期间没有明确的定义类型,编译完成之后会生成一个占位符,只有在调用者调用时,传入指定的类型,才会用确切的类型将占位符替换 ...

  2. 数据集转换为Json

    数据集转换为Json 第一步:新建一个类对象  通常我会写三个属性:状态.返回信息.数据集 第二步:新建一个JSON转换类 第三步:把类对象当做参数传入JSON转换类 ———————————————— ...

  3. 【学习笔记】C#中的泛型和泛型集合

    一.什么是泛型? 泛型是C#语言和公共语言运行库(CLR)中的一个新功能,它将类型参数的概念引入.NET Framework.类型参数使得设计某些类和方法成为可能,例如,通过使用泛型类型参数T,可以大 ...

  4. mormot 数据集转换为JSON字串

    mormot 数据集转换为JSON字串 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graph ...

  5. Scala 深入浅出实战经典 第42讲:scala 泛型类,泛型函数,泛型在spark中的广泛应用

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  6. DataTable 对象 转换为Json 字符串

    /// <summary> /// DataTable 对象 转换为Json 字符串 /// </summary> /// <param name="dt&qu ...

  7. Java基础---Java---基础加强---内省的简单运用、注解的定义与反射调用、 自定义注解及其应用、泛型及泛型的高级应用、泛型集合的综合

    内省的简单运用: JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则. 采用遍历BeanInfo的所有属性方式来查找和 ...

  8. JavaSE学习总结(十六)—— 泛型与泛型应用

    一.泛型概要 泛型(Generic)的本质是类型参数化,通俗的说就是用一个占位符来表示类型,这个类型可以是String,Integer等不确定的类型,表明可接受的类型. 泛型是Java中一个非常重要的 ...

  9. .NET泛型02,泛型的使用

    在" .NET泛型01,为什么需要泛型,泛型基本语法"中,了解了泛型的基本概念,本篇偏重于泛型的使用.主要包括: ■ 泛型方法重载需要注意的问题■ 泛型的类型推断■ 泛型方法也可以 ...

随机推荐

  1. Swift开发第六篇——操作运算符也可以重载& func 的参数修饰

    本篇分为两部分: 1.Swift 中重载操作运算符的使用 2.Swfit 中 func 的参数修饰 1.Swift 中重载操作运算符的使用 与别的语言不同,Swift 支持运算符的重载,运算符指的是“ ...

  2. VIP - virtual IP address

    virtual IP address (虚拟 IP 地址)1.是集群的ip地址,一个vip对应多个机器2.与群集关联的唯一 IP 地址 see wiki: A virtual IP address ( ...

  3. Effective Java 58 Use checked exceptions for recoverable conditions and runtime exceptions for programming errors

    Three kinds of throwables Throwables Checked Recoverable checked exceptions Y Y runtime exceptions N ...

  4. 用mciSendString做音乐播放器

    音乐操作类 public class clsMCI { public clsMCI() { // // TODO: 在此处添加构造函数逻辑 // } //定义API函数使用的字符串变量 [Marsha ...

  5. Centos Ping不通外网

    安装完成Vm,Centos6.5,设置了网络: 1.VM虚拟网络,采用桥接模式. 2.Centos里各种 设置ifcfg-eth0中的GETWAY,ADDIP等等 vim /etc/sysconfig ...

  6. Linux运维工程师入门须掌握的10个技术点

    本人是linux运维工程师,对这方面有点心得,现在我说说要掌握哪方面的工具吧 说到工具,在行外可以说是技能,在行内我们一般称为工具,就是运维必须要掌握的工具. 我就大概列出这几方面,这样入门就基本没问 ...

  7. 使用Azure Automation(自动化)定时关闭和启动虚拟机

    1. 概述 作为Windows Azure的用户,使用Azure的过程中,最担心的事情就是还没到月底,预设的费用就快消耗完了(下面两张账单图是我最讨厌看到的).但是仔细分析自己的费用列表,发现绝大部分 ...

  8. listview中OnItemClick方法各个参数的作用

    OnItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) 1.arg0,arg2 m_listview.setOnI ...

  9. 广度优先搜索 codevs 2806 红与黑

    codevs 2806 红与黑  时间限制: 1 s  空间限制: 64000 KB  题目等级 : 白银 Silver   题目描述 Description 有一个矩形房间,覆盖正方形瓷砖.每块瓷砖 ...

  10. win8程序开机自启动管理

    主要介绍利用系统自身的工具来管理开机自启动,而非第三方的工具,自己了解了,也写出来分享给大家@.·.@ 1.程序设置开机自启动 a. 打开计算机资源管理器-->进入"C:\Progra ...