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

  • 相关阅读:
    ZeptoLab Code Rush 2015
    UVa 10048 Audiophobia【Floyd】
    POJ 1847 Tram【Floyd】
    UVa 247 Calling Circles【传递闭包】
    UVa 1395 Slim Span【最小生成树】
    HDU 4006 The kth great number【优先队列】
    UVa 674 Coin Change【记忆化搜索】
    UVa 10285 Longest Run on a Snowboard【记忆化搜索】
    【NOIP2016提高A组模拟9.28】求导
    【NOIP2012模拟10.9】电费结算
  • 原文地址:https://www.cnblogs.com/hnsongbiao/p/9931569.html
Copyright © 2011-2022 走看看