自用的基于Emit的C#下DataTable转实体类方法
之前一直在做WebForm的开发,数据绑定时直接DataTable绑定Gridview很方便,但是最近开始往MVC转,数据列表的传递和页面展示基本上是以List为主,像下面这样,遍历实体类的各个字段去赋值的办法当然是最浪费时间的。
			if (row["ID"] != null && row["ID"].ToString() != "")
            {
                model.bedID = int.Parse(row["ID"].ToString());
            }
通过在网上查资料和一定的比较,我选择了以下基于Emit的DataTable转实体类的方法。
按照下边的代码新建一个类EntityConverter:
  public static class EntityConverter
  {
        public static List<T> ToList<T>(this DataTable dt) where T : class, new()
        {
            List<T> list = new List<T>();
            if (dt == null || dt.Rows.Count == 0)
                return list;
            DataTableEntityBuilder<T> eblist = DataTableEntityBuilder<T>.CreateBuilder(dt.Rows[0]);
            foreach (DataRow info in dt.Rows)
                list.Add(eblist.Build(info));
            dt.Dispose();
            dt = null;
            return list;
        }
        public class DataTableEntityBuilder<Entity>
        {
            private static readonly MethodInfo getValueMethod = typeof(DataRow).GetMethod("get_Item", new Type[] { typeof(int) });
            private static readonly MethodInfo isDBNullMethod = typeof(DataRow).GetMethod("IsNull", new Type[] { typeof(int) });
            private delegate Entity Load(DataRow dataRecord);
            private Load handler;
            private DataTableEntityBuilder() { }
            public Entity Build(DataRow dataRecord)
            {
                return handler(dataRecord);
            }
            public static DataTableEntityBuilder<Entity> CreateBuilder(DataRow dataRecord)
            {
                DataTableEntityBuilder<Entity> dynamicBuilder = new DataTableEntityBuilder<Entity>();
                DynamicMethod method = new DynamicMethod("DynamicCreateEntity", typeof(Entity), new Type[] { typeof(DataRow) }, typeof(Entity), true);
                ILGenerator generator = method.GetILGenerator();
                LocalBuilder result = generator.DeclareLocal(typeof(Entity));
                generator.Emit(OpCodes.Newobj, typeof(Entity).GetConstructor(Type.EmptyTypes));
                generator.Emit(OpCodes.Stloc, result);
                for (int i = 0; i < dataRecord.ItemArray.Length; i++)
                {
                    PropertyInfo propertyInfo = typeof(Entity).GetProperty(dataRecord.Table.Columns[i].ColumnName);
                    Label endIfLabel = generator.DefineLabel();
                    if (propertyInfo != null && propertyInfo.GetSetMethod() != null)
                    {
                        generator.Emit(OpCodes.Ldarg_0);
                        generator.Emit(OpCodes.Ldc_I4, i);
                        generator.Emit(OpCodes.Callvirt, isDBNullMethod);
                        generator.Emit(OpCodes.Brtrue, endIfLabel);
                        generator.Emit(OpCodes.Ldloc, result);
                        generator.Emit(OpCodes.Ldarg_0);
                        generator.Emit(OpCodes.Ldc_I4, i);
                        generator.Emit(OpCodes.Callvirt, getValueMethod);
                        generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
                        generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod());
                        generator.MarkLabel(endIfLabel);
                    }
                }
                generator.Emit(OpCodes.Ldloc, result);
                generator.Emit(OpCodes.Ret);
                dynamicBuilder.handler = (Load)method.CreateDelegate(typeof(Load));
                return dynamicBuilder;
            }
        }
  }
在DbHelperSQL里面再简单封装一下:
	  public static List<T> Query<T>(string sql) where T : class, new()
        {
            DataTable dt = DbHelperSQL.Query(sql).Tables[0];
            if (dt != null && dt.Rows.Count > 0)
            {
                return EntityConverter.ToList<T>(dt);
            }
            else
            {
                return null;
            }
        }
使用的时候:
	string sql="select top 10 * from user";
	List<Model.User> listUser=DbHelperSQL.Query<Model.User>(sql);
注意:
- 1、定义的Model的各个属性的名称要和Select语句执行结果的列名一致
 - 2、定义的Model的各个属性的数据类型要和数据库定义的一致
 - 3、关于数据列与属性对应:Model中的属性SQL里面可以没有,值会默认为Null/0;但是SQL结果里面有的列名必须在Model中存在。否则会报错!
 
这只是简单的使用,更深层次的需求请参考再谈使用Emit把Datatable转换为对象集合(List) - lindping
原文链接 http://huisky.com/blog/17010514150692
参考资料
- DataTable转Entity(Emit版) - ShuLin
 - 使用Emit把Datatable转换为对象集合(List) - lindping
 - 再谈使用Emit把Datatable转换为对象集合(List) - lindping
 
自用的基于Emit的C#下DataTable转实体类方法的更多相关文章
- 基于Emit的C#下DataTable转实体类方法,一直报错.
		
xxxx ;WITH Tab AS ( SELECT CAST(ROW_NUMBER()OVER(ORDER BY CC.CreateTime DESC) AS INT) AS Sequency, ) ...
 - c#中@标志的作用  C#通过序列化实现深表复制  细说并发编程-TPL  大数据量下DataTable To List效率对比  【转载】C#工具类:实现文件操作File的工具类  异步多线程 Async  .net 多线程 Thread ThreadPool Task  .Net 反射学习
		
c#中@标志的作用 参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...
 - 基于jQuery美化联动下拉选择框
		
今天给大家介绍一款基于jQuery美化联动下拉选择框.这款下下拉选择框js里自带了全国所有城市的数数库.下拉选择框适用浏览器:IE8.360.FireFox.Chrome.Safari.Opera.傲 ...
 - 基于Emit实现的C#版本的BeanCopier
		
在java的技术栈当中,著名的Cglib库里面有一个BeanCopier,这个类的功能就是可以完成两个对象的属性复制工作(哪怕属于两个不同的类). 今天本人通过.net内置的System.Reflec ...
 - 大数据量下DataTable To List效率对比
		
使用反射和动态生成代码两种方式(Reflect和Emit) 反射将DataTable转为List方法 public static List<T> ToListByReflect<T& ...
 - 基于jQuery动画二级下拉导航菜单
		
春节回来给大家分享一款基于jQuery动画二级下拉导航菜单.鼠标经过的时候以动画的形式出现二级导航.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div id=" ...
 - 基于CSS3金属风格下拉菜单
		
基于CSS3金属风格下拉菜单,css,金属风格,下拉菜单,CSS3导航. css3按钮:http://www.huiyi8.com/css3/anniu/
 - 基于Zepto移动端下拉加载(刷新),上拉加载插件开发
		
写在前面:本人水平有限,有什么分析不到位的还请各路大神指出,谢谢. 这次要写的东西是类似于<今日头条>的效果,下拉加载上啦加载,这次做的效果是简单的模拟,没有多少内容,下面是今日头条的移动 ...
 - 菜渣开源一个基于 EMIT 的 AOP 库(.NET Core)
		
目录 1,快速入门 1.1 继承 ActionAttribute 特性 1.2 标记代理类型 2,如何创建代理类型 2.1 通过API直接创建 2,创建代理类型 通过API 通过 Microsoft. ...
 
随机推荐
- Angular2学习笔记(1)
			
Angular2学习笔记(1) 1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之 ...
 - opencv源码:cascadedetect
			
级联分类器检测类CascadeClassifier,提供了两个重要的方法: CascadeClassifier cascade_classifier; cascade_classifier.load( ...
 - 事务日志已满,原因为“ACTIVE_TRANSACTION”
			
汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 异常处理汇总-数据库系列 http://www.cnblogs.com/dunitia ...
 - 【SQLServer】记一次数据迁移-标识重复的简单处理
			
汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 今天在数据迁移的时候因为手贱遇到一个坑爹问题,发来大家乐乐,也传授新手点经验 迁移惯用就 ...
 - 【翻译】MongoDB指南/CRUD操作(一)
			
[原文地址]https://docs.mongodb.com/manual/ MongoDB CRUD操作(一) 主要内容:CRUD操作简介,插入文档,查询文档. CRUD操作包括创建.读取.更新和删 ...
 - EditText 基本用法
			
title: EditText 基本用法 tags: EditText,编辑框,输入框 --- EditText介绍: EditText 在开发中也是经常用到的控件,也是一个比较必要的组件,可以说它是 ...
 - QT5利用chromium内核与HTML页面交互
			
在QT5.4之前,做QT开发浏览器只能选择QWebkit,但是有过使用的都会发现,这个webkit不是出奇的慢,简直是慢的令人发指,Release模式下还行,debug下你就无语了,但是webkit毕 ...
 - spring源码分析之freemarker整合
			
FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页.电子邮件.配置文件.源代码等)的通用工具. 它不是面向最终用户的,而是一个Java类库,是一款程 ...
 - 深入node之Transform
			
Transform流特性 在开发中直接接触Transform流的情况不是很多,往往是使用相对成熟的模块或者封装的API来完成流的处理,最为特殊的莫过于through2模块和gulp流操作.那么,Tra ...
 - 如何搭建git服务器
			
一.前言 现在越来越多的公司用git进行版本控制,不过git是默认是开源的,如果私有的话是需要付费的,如果不想付费自己可以搭建一个git服务器用来版本控制. 二.服务器端操作 1.安装git sudo ...