标签:types 赋值 数据库 property new build 封装 name 利用反射
原文:利用反射将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读取到实体类中效率低下的解决办法
标签:types 赋值 数据库 property new build 封装 name 利用反射
原文地址:https://www.cnblogs.com/lonelyxmas/p/10317643.html