利用反射将IDataReader读取到实体类中效率低下的解决办法

原文:利用反射将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 = 0; 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

原文地址:https://www.cnblogs.com/lonelyxmas/p/10317643.html

时间: 2024-10-14 20:54:30

利用反射将IDataReader读取到实体类中效率低下的解决办法的相关文章

java 中利用反射机制获取和设置实体类的属性值

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. JAVA反射(放射)机制:"程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言".从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言.但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可

数据库中信息存放到 实体类中

把数据库中信息存放到 实体类中,实体类设置值 Tb_pay tb_pay = payDAO.find(userid,Integer.parseInt(strno)); txtMoney.setText(String.valueOf(tb_pay.getMoney()));// 显示金额 txtTime.setText(tb_pay.getTime());// 显示时间 spType.setSelection(tb_pay.getType()-1);// 显示类别 txtHA.setText(tb

Hibernate在实体类中对于时间的注解

在时间类型DATE 属性上添加一个 @Temporal(TemporalType.DATE)(精确到年月日)@Temporal(TemporalType.TIME)(精确到时分秒)@Temporal(TemporalType.TIMESTAMP)(默认年月日时分秒)示例: @Temporal(TemporalType.DATE)private Date updateDate; 有了这个就不需要用java代码将时间戳,转换成需要的日期格式.直接在实体类中进行注解!

struct框架中实体类中属性的类型错误问题

在struct框架中,我们会写出实体类然后再sqlmap中进行映射,通常我们都知道 java中date类型有java.sql.date 和 java.util.date 经过细心发现,将对象生成为json对象时,json类会将date类型转换成java.util.date 如果在实体类中写成java.sql.date,就会抛出异常 下面我就来传个图 这里仅仅只需要把实体中date类型导入的包改成util的便不会出错 有人说util的包更常用,其实sql包中的直接输入就和我们平时写的时间的差不多,

MyBatis系列二 之 数据库列名于程序实体类中字段名称不一致

MyBatis系列二  之   数据库列名于程序实体类中字段名称不一致 情景:当数据库中的列名与我们程序实体类中的字段名称不一致         使用ResultMap节点配置信息  在映射文件中  mapper根节点下配置ResultMap节点信息 <resultMap type="Student" id="studentMapper"> <result column="sname" property="stunam

使用sqlServer数据库,实体类中的配置问题

1.使用sqlServer数据库,实体类中的xml的配置问题(目前还没有去试试使用mysql的时候是否也是这样的写法) 1.1 在实体类的xml中调用自己在数据库中写的函数 对应的数据库中的函数,函数中的问好代表的是传入的参数

在动态sql的使用where时,if标签判断中,如果实体类中的某一个属性是String类型,那么就可以这样来判断连接语句:

如果是String类型的字符串进行判空的时候: <if test="inspectOrg != null and inspectOrg != ''"> INSPECT_ORG = #{inspectOrg} </if> 但是如果是实体类中的Integer类型,就是去掉空字符串的判断: <if test="inspectTaio != null"> AND INSPECT_TAIO = #{inspectTaio} </if&

Intellij IDEA ,按Ctrl+左键,不能进入类或方法的【解决办法】,提示Cannot find declaration to go to

Intellij IDEA ,按Ctrl+左键,不能进入类或方法的[解决办法],提示Cannot find declaration to go to 2017年8月4日 朱宏亮%1 $ S 如图,,按住Ctrl+鼠标单击的时候,系统提示Cannot find declaration to go to. 原因:导入项目的时候使用的是Open而不是Import Project. 解决方法:关闭当前项目,如图点击Import PrOject,导入项目即可 原文地址:https://www.cnblog

利用反射与dom4j读取javabean生成对应XML和读取XML得到对应的javabean对象集合

转自:http://blog.csdn.net/zhao19861029/article/details/8473245 首先实现生成对应的JAVAbean的XML文件方法 /** * DMO4J写入XML * @param obj 泛型对象 * @param entityPropertys 泛型对象的List集合 * @param Encode XML自定义编码类型(推荐使用GBK) * @param XMLPathAndName XML文件的路径及文件名 */ public void wri