大数据量下DataTable To List效率对比
程序员文章站
2022-06-28 20:54:34
使用反射和动态生成代码两种方式(Reflect和Emit) 反射将DataTable转为List方法 1 public static List ToListByReflect(this DataTable dt) where T : new() 2 { 3 List ts = ne ......
使用反射和动态生成代码两种方式(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反而比较快。
下一篇: Python元组常见操作示例