前言

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. 自动生成makefile的脚本

    如果需要测试某一个特性,写了一个test.cpp 某天又增加了一个utils.cpp,依此类推,测试文件越来越多 每次测试时都要手动维护一个makefile实在是不明智的 于是萌生了用脚本自动维护的念 ...

  2. JSP中使用的模式——JSP+Servlet+JavaBean

    上一篇博文写到模式一:JSP+JavaBean 链接地址:http://wxmimperio.coding.io/?p=155 JSP中两种模式的总结 链接地址:http://wxmimperio.c ...

  3. 区分html与css中的属性

    CSS中id与Class的区别 1.在CSS文件里书写时,ID加前缀"#":CLASS用"." 2.id一个页面只可以使用一次:class可以多次引用. 3.I ...

  4. 《agile java》First : 起步 + 章节练习题

    第一章节:起步 1.创建简单Java类2.创建测试类3.使用JUnit4.学习构造函数5.重构代码 涉及知识:TDD.UML TDD: Test Driven Development, 测试驱动开发. ...

  5. linux socket使用经验总结

    1.  scoket函数中PF_INET AF_INET区别 在UNIX系列中,PF_INET表示poxis, BSD系列用AF_INET 2.  in_addr_t inet_addr(const ...

  6. bzoj 1051: [HAOI2006]受欢迎的牛 tarjan缩点

    1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2092  Solved: 1096[Submit][Sta ...

  7. 使用Python实现Hadoop MapReduce程序

    转自:使用Python实现Hadoop MapReduce程序 英文原文:Writing an Hadoop MapReduce Program in Python 根据上面两篇文章,下面是我在自己的 ...

  8. RemixOS Player 让用户在 Windows 上运行 Android App

    http://www.oschina.net/news/77154/remixos-player-windows-andriod-app

  9. 代理Delegate的小应用(代理日期控件和下拉框)

    前言 在平时关于表格一类的的控件使用中,不可避免需要修改每个Item的值,通过在Item中嵌入不同的控件对编辑的内容进行限定,然而在表格的Item中插入的控件始终显示,当表格中item项很多的时候,会 ...

  10. sublime配置python开发

    想在sublime里要python shell那种交互或者run module F5 F5 F5下这种效果的话,还是挺容易实现的,windows下的:1. 打开Sublime text 3 安装pac ...