前言

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

table转list的更多相关文章

  1. 散列表(hash table)——算法导论(13)

    1. 引言 许多应用都需要动态集合结构,它至少需要支持Insert,search和delete字典操作.散列表(hash table)是实现字典操作的一种有效的数据结构. 2. 直接寻址表 在介绍散列 ...

  2. React使用antd Table生成层级多选组件

    一.需求 用户对不同的应用需要有不同的权限,用户一般和角色关联在一起,新建角色的时候会选择该角色对应的应用,然后对应用分配权限.于是写了一种实现的方式.首先应用是一个二级树,一级表示的是应用分组,二级 ...

  3. 创建几个常用table展示方式插件

    这次和大家分享的是自己写的一个table常用几种展示格式的js插件取名为(table-shenniu),样式使用的是bootstrap.min.css,还需要引用jquery.min.js包,这个插件 ...

  4. html中table边框属性

    1.向右(横向)合并: <td colspan="5"><span>后台管理系统</span></td> 2.向下(纵向)合并: & ...

  5. MySQL中You can't specify target table for update in FROM clause一场

    mysql中You can't specify target table <tbl> for update in FROM clause错误的意思是说,不能先select出同一表中的某些值 ...

  6. 打印Lua的Table对象

    小伙伴们再也不用为打印lua的Table对象而苦恼了, 本人曾也苦恼过,哈哈 不过今天刚完成了这个东西, 以前在网上搜过打印table的脚本,但是都感觉很不理想,于是,自己造轮子了~ 打印的效果,自己 ...

  7. React中使用Ant Table组件

    一.Ant Design of React http://ant.design/docs/react/introduce 二.建立webpack工程 webpack+react demo下载 项目的启 ...

  8. css设置table表格tr分离

    table { border-collapse:separate; border-spacing:10px 50px; }

  9. MySQL: Table 'mysql.plugin' doesn't exist的解决

    安装解压版MySQL以后,不能启动,日志里面出现了这个错误: MySQL: Table 'mysql.plugin' doesn't exist 这是因为mysql服务启动时候找不到内置数据库&quo ...

  10. js操作table表格导出数据到excel方法

    js导出excel资料很少,网上也找了很多,基本都不能用,要么只能是IE用,还必须要权限,这是非常不好的.后来到github上找到table2excel.js,虽然可以用,但仍然对IE支持不够,也算不 ...

随机推荐

  1. HttpRuntime类的缓存以及redis,memercache

    http://www.cnblogs.com/kissdodog/archive/2013/05/07/3065208.html

  2. bzoj 2705: [SDOI2012]Longge的问题 歐拉函數

    2705: [SDOI2012]Longge的问题 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1035  Solved: 669[Submit][S ...

  3. BZOJ 4010 菜肴制作

    Description 知名美食家小A被邀请至ATM 大酒店,为其品评菜肴. ATM酒店为小A准备了\(N\)道菜肴,酒店按照为菜肴预估的质量从高到低给予\(1\)到\(N\)的顺序编号,预估质量最高 ...

  4. ping命令找不到

    重装系统后安装JDK了,网络一直不好,我ping了下,结果显示ping不是内部或者外部命令,在谷歌里百度了下,在环境变量的path后加上“;C:\Windows\System32”即可,果然有效哦. ...

  5. angularjs编码实践

    AngularJS 是制作 SPA(单页面应用程序)和其它动态Web应用最广泛使用的框架之一.我认为程序员在使用AngularJS编码时有一个大的列表点应该记住,它会以这样或那样的方式帮助到你.下面是 ...

  6. Web-Scale-IT 到底是啥?

    Gartner 对 2015 年 10 大 IT 趋势的预测中有一个词条为:Web Scale IT.我们跟随 Matthias Ankli 来了解一下究竟什么是 Web Scale IT.本文译自 ...

  7. 性能指标--并发用户数(Concurrent Users)

    并发用户数是指:在某一时间点,与被测目标系统同时进行交互的客户端用户的数量. 并发用户数有以下几种含义: 1. 并发虚拟用户数(Concurrent Virtual Users,Users_CVU) ...

  8. Win32中常用消息

    一 .WM_PAINT消息 1 WM_PAINT的产生   由于窗口的互相覆盖等,产生需要绘制的区域,那么会产生WM_PAINT消息. 一般情况下,不直接发送WM_PAINT消息,通过API声明需要绘 ...

  9. [QT]构建正则表达式测试

    正则表达式是个强大的东西 暂时先记录一个用法: QString str = "Peak memory: KEY s"; QString data = "Peak memo ...

  10. hdu 4278 Faulty Odometer

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4278 #include<cstdio> #include<cstring> # ...