zoukankan      html  css  js  c++  java
  • 利用反射将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

  • 相关阅读:
    IELTS Writing Task 2: 'music' essay
    leetcode 368. 最大整除子集
    820复试算法 快排找第 k 小
    ASP.NET后台生成随机验证码
    Oracle身份证验证方法
    ASP.NET 存储过程导入(oracle)返回导入成功数和导入失败数
    C#执行参数为游标 返回一个记录集的Oracle存储过程
    C#执行带参数的Oracle存储过程
    往ORACLE数据库中插入XML数据
    存储过程 将数据插入到临时表,再根据条件判断 插入到不同的表
  • 原文地址:https://www.cnblogs.com/hnsongbiao/p/9931569.html
Copyright © 2011-2022 走看看