之前一直在做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

参考资料

自用的基于Emit的C#下DataTable转实体类方法的更多相关文章

  1. 基于Emit的C#下DataTable转实体类方法,一直报错.

    xxxx ;WITH Tab AS ( SELECT CAST(ROW_NUMBER()OVER(ORDER BY CC.CreateTime DESC) AS INT) AS Sequency, ) ...

  2. 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 ...

  3. 基于jQuery美化联动下拉选择框

    今天给大家介绍一款基于jQuery美化联动下拉选择框.这款下下拉选择框js里自带了全国所有城市的数数库.下拉选择框适用浏览器:IE8.360.FireFox.Chrome.Safari.Opera.傲 ...

  4. 基于Emit实现的C#版本的BeanCopier

    在java的技术栈当中,著名的Cglib库里面有一个BeanCopier,这个类的功能就是可以完成两个对象的属性复制工作(哪怕属于两个不同的类). 今天本人通过.net内置的System.Reflec ...

  5. 大数据量下DataTable To List效率对比

    使用反射和动态生成代码两种方式(Reflect和Emit) 反射将DataTable转为List方法 public static List<T> ToListByReflect<T& ...

  6. 基于jQuery动画二级下拉导航菜单

    春节回来给大家分享一款基于jQuery动画二级下拉导航菜单.鼠标经过的时候以动画的形式出现二级导航.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div id=" ...

  7. 基于CSS3金属风格下拉菜单

    基于CSS3金属风格下拉菜单,css,金属风格,下拉菜单,CSS3导航. css3按钮:http://www.huiyi8.com/css3/anniu/

  8. 基于Zepto移动端下拉加载(刷新),上拉加载插件开发

    写在前面:本人水平有限,有什么分析不到位的还请各路大神指出,谢谢. 这次要写的东西是类似于<今日头条>的效果,下拉加载上啦加载,这次做的效果是简单的模拟,没有多少内容,下面是今日头条的移动 ...

  9. 菜渣开源一个基于 EMIT 的 AOP 库(.NET Core)

    目录 1,快速入门 1.1 继承 ActionAttribute 特性 1.2 标记代理类型 2,如何创建代理类型 2.1 通过API直接创建 2,创建代理类型 通过API 通过 Microsoft. ...

随机推荐

  1. Angular2学习笔记(1)

    Angular2学习笔记(1) 1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之 ...

  2. opencv源码:cascadedetect

    级联分类器检测类CascadeClassifier,提供了两个重要的方法: CascadeClassifier cascade_classifier; cascade_classifier.load( ...

  3. 事务日志已满,原因为“ACTIVE_TRANSACTION”

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 异常处理汇总-数据库系列  http://www.cnblogs.com/dunitia ...

  4. 【SQLServer】记一次数据迁移-标识重复的简单处理

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 今天在数据迁移的时候因为手贱遇到一个坑爹问题,发来大家乐乐,也传授新手点经验 迁移惯用就 ...

  5. 【翻译】MongoDB指南/CRUD操作(一)

    [原文地址]https://docs.mongodb.com/manual/ MongoDB CRUD操作(一) 主要内容:CRUD操作简介,插入文档,查询文档. CRUD操作包括创建.读取.更新和删 ...

  6. EditText 基本用法

    title: EditText 基本用法 tags: EditText,编辑框,输入框 --- EditText介绍: EditText 在开发中也是经常用到的控件,也是一个比较必要的组件,可以说它是 ...

  7. QT5利用chromium内核与HTML页面交互

    在QT5.4之前,做QT开发浏览器只能选择QWebkit,但是有过使用的都会发现,这个webkit不是出奇的慢,简直是慢的令人发指,Release模式下还行,debug下你就无语了,但是webkit毕 ...

  8. spring源码分析之freemarker整合

    FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页.电子邮件.配置文件.源代码等)的通用工具. 它不是面向最终用户的,而是一个Java类库,是一款程 ...

  9. 深入node之Transform

    Transform流特性 在开发中直接接触Transform流的情况不是很多,往往是使用相对成熟的模块或者封装的API来完成流的处理,最为特殊的莫过于through2模块和gulp流操作.那么,Tra ...

  10. 如何搭建git服务器

    一.前言 现在越来越多的公司用git进行版本控制,不过git是默认是开源的,如果私有的话是需要付费的,如果不想付费自己可以搭建一个git服务器用来版本控制. 二.服务器端操作 1.安装git sudo ...