大数据量下DataTable To List效率对比
Posted liunew
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大数据量下DataTable To List效率对比相关的知识,希望对你有一定的参考价值。
使用反射和动态生成代码两种方式(Reflect和Emit)
反射将DataTable转为List方法
1 public static List<T> ToListByReflect<T>(this DataTable dt) where T : new() 2 { 3 List<T> ts = new List<T>(); 4 string tempName = string.Empty; 5 foreach (DataRow dr in dt.Rows) 6 { 7 T t = new T(); 8 PropertyInfo[] propertys = t.GetType().GetProperties(); 9 foreach (PropertyInfo pi in propertys) 10 { 11 tempName = pi.Name; 12 if (dt.Columns.Contains(tempName)) 13 { 14 object value = dr[tempName]; 15 if (value != DBNull.Value) 16 { 17 pi.SetValue(t, value, null); 18 } 19 } 20 } 21 ts.Add(t); 22 } 23 return ts; 24 }
动态生成代码将DataTable转为List方法
1 public static List<T> ToListByEmit<T>(this DataTable dt) where T : class, new() 2 { 3 List<T> list = new List<T>(); 4 if (dt == null || dt.Rows.Count == 0) 5 return list; 6 DataTableEntityBuilder<T> eblist = DataTableEntityBuilder<T>.CreateBuilder(dt.Rows[0]); 7 foreach (DataRow info in dt.Rows) 8 list.Add(eblist.Build(info)); 9 dt.Dispose(); 10 dt = null; 11 return list; 12 } 13 public class DataTableEntityBuilder<Entity> 14 { 15 private static readonly MethodInfo getValueMethod = typeof(DataRow).GetMethod("get_Item", new Type[] { typeof(int) }); 16 private static readonly MethodInfo isDBNullMethod = typeof(DataRow).GetMethod("IsNull", new Type[] { typeof(int) }); 17 private delegate Entity Load(DataRow dataRecord); 18 private Load handler; 19 private DataTableEntityBuilder() { } 20 public Entity Build(DataRow dataRecord) 21 { 22 return handler(dataRecord); 23 } 24 public static DataTableEntityBuilder<Entity> CreateBuilder(DataRow dataRecord) 25 { 26 DataTableEntityBuilder<Entity> dynamicBuilder = new DataTableEntityBuilder<Entity>(); 27 DynamicMethod method = new DynamicMethod("DynamicCreateEntity", typeof(Entity), new Type[] { typeof(DataRow) }, typeof(Entity), true); 28 ILGenerator generator = method.GetILGenerator(); 29 LocalBuilder result = generator.DeclareLocal(typeof(Entity)); 30 generator.Emit(OpCodes.Newobj, typeof(Entity).GetConstructor(Type.EmptyTypes)); 31 generator.Emit(OpCodes.Stloc, result); 32 for (int i = 0; i < dataRecord.ItemArray.Length; i++) 33 { 34 PropertyInfo propertyInfo = typeof(Entity).GetProperty(dataRecord.Table.Columns[i].ColumnName); 35 Label endIfLabel = generator.DefineLabel(); 36 if (propertyInfo != null && propertyInfo.GetSetMethod() != null) 37 { 38 generator.Emit(OpCodes.Ldarg_0); 39 generator.Emit(OpCodes.Ldc_I4, i); 40 generator.Emit(OpCodes.Callvirt, isDBNullMethod); 41 generator.Emit(OpCodes.Brtrue, endIfLabel); 42 generator.Emit(OpCodes.Ldloc, result); 43 generator.Emit(OpCodes.Ldarg_0); 44 generator.Emit(OpCodes.Ldc_I4, i); 45 generator.Emit(OpCodes.Callvirt, getValueMethod); 46 generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType); 47 generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod()); 48 generator.MarkLabel(endIfLabel); 49 } 50 } 51 generator.Emit(OpCodes.Ldloc, result); 52 generator.Emit(OpCodes.Ret); 53 dynamicBuilder.handler = (Load)method.CreateDelegate(typeof(Load)); 54 return dynamicBuilder; 55 } 56 }
然后写个控制台程序,对比一下两个方法的效率(测试类大概有40个属性)
电脑比较渣,使用Emit方法转换100w条数据大概需要7秒,而反射则需要37秒。还测试了当数据量比较小时,Reflect反而比较快。
以上是关于大数据量下DataTable To List效率对比的主要内容,如果未能解决你的问题,请参考以下文章