前言

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. wndows 7 Wifi热点

    2016年09月13日 14時52分 wanglinqiang整理 Step1 cmd.exe(管理员身份运行) Step2 命令行输入[netsh wlan set hostednetwork mo ...

  2. hadoop 异常处理实例(一)hadoop内存配置项

    Exception in thread "main" java.io.IOException: Job failed! at org.apache.hadoop.mapred.Jo ...

  3. bzoj 1503: [NOI2004]郁闷的出纳员 Treap

    1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 6263  Solved: 2190[Submit][Statu ...

  4. mysql 2006

    1.在my.ini文件中添加或者修改以下两个变量:wait_timeout=2880000interactive_timeout = 2880000 关于两个变量的具体说明可以google或者看官方手 ...

  5. Android 使用HttpClient方式提交POST请求

    final String username = usernameEditText.getText().toString().trim(); final String password = passwr ...

  6. KeilC51使用详解 (二)

    深入理解并应用C51对标准ANSIC的扩展是学习C51的关键之一.因为大多数扩展功能都是直接针对8051系列CPU硬件的.大致有以下8类: 8051存储类型及存储区域 存储模式 存储器类型声明 变量类 ...

  7. Spring messageSource

    Spring中可以使用两个类加载资源文件: org.springframework.context.support.ReloadableResourceBundleMessageSource 和 or ...

  8. leetcode面试准备:Count Complete Tree Nodes

    1 题目 Given a complete binary tree, count the number of nodes. In a complete binary tree every level, ...

  9. 优雅的让Fragment监听返回键

    转载请注明出处:http://write.blog.csdn.net/postedit/40507387 Activity可以很容易的得到物理返回键的监听事件,而Fragment却不能.假设Fragm ...

  10. Response.ContentType 详细列表 <转>

    Response.ContentType 详细列表   不同的ContentType 会影响客户端所看到的效果.默认的ContentType为 text/html 也就是网页格式.代码如: <% ...