前言

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. iOS 摇一摇

    - (void)viewDidLoad { [super viewDidLoad]; [[UIApplication sharedApplication] setApplicationSupports ...

  2. quote、cite、refer的区别

    quote指“直引”,直接引用原文,不做丝毫修改. cite指“间引”,引用时不需要相同的词. refer指消化原来的思想,完全不抄.

  3. 又一个悬而未决的bug被解决

    之所以叫悬而未决,是因为从我第一次见到这个bug,到现在大概已经过了快两年的时间,期间好几次想解决这个问题,但是一直碍于环境和一些技术上的限制,没有解决,直到昨天在一系列的因素作用下,终于解决了这个问 ...

  4. python sorted用法

    python列表排序 python字典排序 sorted List的元素可以是各种东西,字符串,字典,自己定义的类等. sorted函数用法如下: sorted(data, cmp=None, key ...

  5. docker-4 Dockerfile的使用

    Dockerfile FROM      基础镜像 MAINTAINER  维护这信息 RUN       运行什么命令,在命令前面加上RUN ADD       往里面加点文件,copy文件,会自动 ...

  6. wireshark安装

    原文链接地址:http://blog.csdn.net/holandstone/article/details/47026213 Wireshark下载地址:https://www.wireshark ...

  7. Fragment学习笔记

    Fragment为大量型号,尺寸,分辨率的设备提供了一种统一的UI优化方案.将Activity分解为多个Fragment,将极大地提高UI的灵活性,也更容易为一些新的设备配置带来更好的用户体验. on ...

  8. fork函数

    在Unix/Linux中用fork函数创建一个新的进程.进程是由当前已有进程调用fork函数创建,分叉的进程叫子进程,创建者叫父进程.该函数的特点是调用一次,返回两次,一次是在父进程,一次是在子进程. ...

  9. 树莓派3 安装ubuntu-mate

    1.系统安装 1.1.下载ubuntu-mate镜像:https://ubuntu-mate.org/raspberry-pi/ 下载SDFormatterv4:https://www.sdcard. ...

  10. jsp EL 表达式

    EL表达式 EL 全名为Expression Language EL 语法很简单,它最大的特点就是使用上很方便.接下来介绍EL主要的语法结构: ${sessionScope.user.sex} 所有E ...