利用反射将IDataReader读取到实体类中效率低下的解决办法
最开始使用反射一个类型的各个属性,对气进行赋值的代码如下:
public static List<T> ToList<T>(IDataReader reader)
{
//实例化一个List<>泛型集合
List<T> DataList = new List<T>();
PropertyInfo[] properties = typeof(T).GetProperties().Union(typeof(T).BaseType.GetProperties()).ToArray();
while (reader.Read())
{
T RowInstance = Activator.CreateInstance<T>();//动态创建数据实体对象
//通过反射取得对象所有的Property
foreach (PropertyInfo Property in properties)
{
try
{
//取得当前数据库字段的顺序
int Ordinal = reader.GetOrdinal(Property.Name);
if (reader.GetValue(Ordinal) != DBNull.Value)
{
//将DataReader读取出来的数据填充到对象实体的属性里
Property.SetValue(RowInstance, Convert.ChangeType(reader.GetValue(Ordinal), Property.PropertyType), null);
}
}
catch
{
break;
}
}
DataList.Add(RowInstance);
}
return DataList;
}
以上代码封装一个320条记录、50个字段属性耗时13000豪秒,体验相当差。
后来改用以下这种方式后,性能大幅提升,同样是320条记录、50个字段仅用时17-26毫秒:
public class IDataReaderEntityBuilder<Entity>
{
private static readonly MethodInfo getValueMethod = typeof(IDataRecord).GetMethod("get_Item", new Type[] { typeof(int) });
private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod("IsDBNull", new Type[] { typeof(int) });
private delegate Entity Load(IDataRecord dataRecord); private Load handler;
private IDataReaderEntityBuilder() { } public Entity Build(IDataRecord dataRecord) { return handler(dataRecord); } public static IDataReaderEntityBuilder<Entity> CreateBuilder(IDataRecord dataRecord)
{
IDataReaderEntityBuilder<Entity> dynamicBuilder = new IDataReaderEntityBuilder<Entity>();
DynamicMethod method = new DynamicMethod("IDataReaderDynamicCreateEntity", typeof(Entity), new Type[] { typeof(IDataRecord) }, 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); var properties = typeof(Entity).GetProperties();
for (int i = ; i < dataRecord.FieldCount; i++)
{
PropertyInfo propertyInfo = typeof(Entity).GetProperty(properties.FirstOrDefault(x=>x.Name.ToUpper().Equals(dataRecord.GetName(i)))?.Name);
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;
}
}
调用方式如下:
public static List<T> ReaderToEntity<T>(IDataReader reader)
{
//实例化一个List<>泛型集合
List<T> list = new List<T>();
var builder = IDataReaderEntityBuilder<T>.CreateBuilder(reader);
while (reader.Read())
{
var entity = builder.Build(reader);
list.Add(entity);
}
return list;
}
反射慎用,奇慢无比。
相关参考:https://blog.csdn.net/livexy/article/details/6196193
http://www.cnblogs.com/liucfy/archive/2010/03/26/1696196.html
https://blog.csdn.net/lijing_zhaisky/article/details/7434622
https://www.cnblogs.com/livexy/archive/2010/09/01/1815330.html
---------------------
作者:bashigufen
来源:CSDN
原文:https://blog.csdn.net/lilong_herry/article/details/79993907
利用反射将IDataReader读取到实体类中效率低下的解决办法的更多相关文章
- java 中利用反射机制获取和设置实体类的属性值
摘要: 在java编程中,我们经常不知道传入自己方法中的实体类中到底有哪些方法,或者,我们需要根据用户传入的不同的属性来给对象设置不同的属性值,那么,java自带的反射机制可以很方便的达到这种目的,同 ...
- 利用反射拿到并递归C#类中的各个字段名字及类型
以下方法实现了遍历一个class中所有的字段, 并且递归遍历sub class. private StringBuilder _properties = new StringBuilder() ...
- 利用反射跟自定义注解拼接实体对象的查询SQL
前言 项目中虽然有ORM映射框架来帮我们拼写SQL,简化开发过程,降低开发难度.但难免会出现需要自己拼写SQL的情况,这里分享一个利用反射跟自定义注解拼接实体对象的查询SQL的方法. 代码 自定义注解 ...
- 读取Excel文件存储在实体类中
1.Maven文件 <!--读取Excel的架包--> <dependency> <groupId>org.apache.poi</groupId> & ...
- 使用反射机制实现jQuery调用ashx类中的指定方法
使用反射机制实现jQuery调用ashx类中的指定方法 近期用asp.net做个小网站,但又不喜欢使用asp.net的服务器端控件,经过一番思量后确定前端采用原始的html.后台采用Linq to ...
- Hibernate jpa 在实体类中对于时间的注解
在时间类型DATE 属性上添加一个 @Temporal(TemporalType.DATE)(精确到年月日)@Temporal(TemporalType.TIME)(精确到时分秒)@Temporal( ...
- C#:实体类中做数据验证
主要是在实体类中验证 using System; namespace Jone.Function.attribute{ /// <summary> /// 附加 ...
- 尚硅谷面试第一季-11MyBatis中当实体类中的属性名和表中的字段名不一样怎么办
问题: MyBatis中当实体类中的属性名和表中的字段名不一样 ,怎么办 ? 解决方案: 1.写sql语句时起别名 <!-- id属性:必须是接口中方法的方法名 resultType属性:必须是 ...
- 当实体类中entity/DTO/VO等类中,有枚举值,应该怎么输出?
当实体类中entity/DTO/VO等类中,有枚举值,应该怎么输出? 问题: orderStatus 和 payStatus都是枚举类,并且枚举的个数达地10来个,我们不可能在模板页面(jsp/ftl ...
随机推荐
- Spring MVC深入学习
一.MVC思想 MVC思想简介: MVC并不是java所特有的设计思想,也不是Web应用所特有的思想,它是所有面向对象程序设计语言都应该遵守的规范:MVC思想将一个应用部分分成三个基本部 ...
- Django 提交 form 表单
创建 Django 的过程可以参考上一篇文章 https://www.cnblogs.com/klvchen/p/10601536.html 在 templates 文件夹下创建一个 index.ht ...
- 第十课html5 新增标签及属性 html5学习5
一.常用新增标签 1.header:定义页面的页眉头部 2.nav:定义导航栏 3.footer:定义页面底部,页脚 4.article:定义文章 5.section:定义区域 6.aside:定义侧 ...
- 【设计模式】工厂方法模式 Factory Method Pattern
在简单工厂模式中产品的创建统一在工厂类的静态工厂方法中创建,体现了面形对象的封装性,客户程序不需要知道产品产生的细节,也体现了面向对象的单一职责原则(SRP),这样在产品很少的情况下使用起来还是很方便 ...
- selenium-确认进入了预期页面
selenium确认进入了预期页面 在自动化操作中,浏览器每次进入一个新的需要,都需要确认该页面是否打开或打开的页面是否是预期的页面 需要进行确认页面后方可进行下一步操作 确认页面有很多中方法,像每个 ...
- 使用 prismjs 在网页中高亮显示代码
最近在总结这一年来制作的网页模块,网站风格统一的情况下,网站页面结构不会改变,因此想记录一部分网站中统一的结构,方便日后维护. 用到的相关技术: vue, element-ui, prismjs, v ...
- Storm入门-Storm与Spark对比
作为一名程序员通病就是不安分,对业界的技术总要折腾一番,哪怕在最终实际工作中应用到的就那么一点.最近自己准备入门Storm学习,关于流式大数据框架目前比较流行的有Spark和Storm等,在入门之前, ...
- uboot的启动过程-FDT
uboot的启动过程,省略了汇编部分之后,第一个执行函数是board_init_f(),在uboot/common目录的board_f.c中 board_init_f函数,首先初始化了全局数据 # ...
- 题解 P1944 最长括号匹配_NOI导刊2009提高(1)
栈,模拟 把每个元素逐个入栈 如果和栈顶元素匹配,那么一块弹出去,同时标记这里是可匹配的. 取出连续的,最长的可匹配的序列即可. #include <iostream> #include ...
- pyqt5在textBrowser添加文本并自动滑动到底
pyqt5在textBrowser添加文本并自动滑动到底 说明: 1.按下按钮pushButton,把单行文本框lineEdit里的内容循环不断的添加到多行文本展示框textBrowser.2.必须要 ...