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

Posted lonelyxmas

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用反射将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








以上是关于利用反射将IDataReader读取到实体类中效率低下的解决办法的主要内容,如果未能解决你的问题,请参考以下文章

ERP中反射的两个实例

从数据库读取数据后利用反射为对应的实体类的属性赋值

使用反射将DataTable的数据转成实体类

利用反射机制自动获取某个类中的属性,以及获取和设置每个属性对应的值

java反射获取一个实体类中的另外一个实体类中属性的值,两个实体类是关联关系。

java利用映射表名称反射创建实体类并赋属性值