利用反射将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 ...
随机推荐
- 安卓5.0系统怎么无Root激活XPOSED框架的方法
在大多团队的引流或业务操作中,基本上都需要使用安卓的强大Xposed框架,几天前,我们团队买来了一批新的安卓5.0系统,基本上都都是基于7.0以上系统,基本上都不能够获得Root的su权限,纵然一些能 ...
- 如何创建ChromeApp
一个ChromeAPP 包含以下内容: 1. 清单文件 manifest.json,列出应用的一些基本信息例如:如何启动应用,应用的权限等等. 2. 事件处理页面也就是我们常说的后台脚本(backgr ...
- 码云代码托管平台与TortoiseSVN的使用
1.到https://gitee.com/进行注册,然后登陆 可以发现可以将项目设为私有 2.下载tortoisesvn,一路next安装即可 3.项目创建 4.下载项目 5.创建文件并提交 6.如何 ...
- C#断点调试时属性get块逻辑执行多次
上面的例中,当打断点调试时,断点断住时, Attr1属性的get块就会执行一次. 两个断点加在逻辑中对Attr1的访问,最后发现CTest get Attr1.打印了3次. 得到的结论是:多余的2次打 ...
- python3 re模块正则匹配字符串中的时间信息
匹配时间: # -*- coding:utf-8 -*- import re def parseDate(l): patternForTime = r'(\d{4}[\D]\d{1,2}[\D]\d{ ...
- yum方式安装kubernetes
环境准备 master01 node01 node02,连通网络,修改hosts文件,确认3台主机相互解析 vim /etc/hosts 127.0.0.1 localhost localhost.l ...
- Java基础系列--08_集合1
---恢复内容开始--- 集合当中有很多都是应用到泛型的技术,所以在讲集合之前,应该先将泛型的概念普及一下. 泛型: (1)泛型是一种类型,但是这种类型是在编译或者调用方法时才确定. (2 ...
- Python开发 文件操作
阅读目录 1.读写文件 open()将会返回一个file对象,基本语法: open(filename,mode) filename:是一个包含了访问的文件名称的路径字符串 mode:决定了打开文件的模 ...
- 移动端键盘密码输入框插件(jquery用于支付密码)
最后生成样子: 配置值: * back {function} 回调函数 * msghtml {html} 自定义的html * title {string|object} 标题 * {txt:标题,b ...
- python接口自动化-session_自动发文
一.session简介 查看 requests.session() 帮助文档(只贴了一部分内容) import requests help(requests.session()) class Sess ...