大数据量下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         }
View Code

动态生成代码将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         }
View Code

然后写个控制台程序,对比一下两个方法的效率(测试类大概有40个属性)

技术图片

电脑比较渣,使用Emit方法转换100w条数据大概需要7秒,而反射则需要37秒。还测试了当数据量比较小时,Reflect反而比较快。

以上是关于大数据量下DataTable To List效率对比的主要内容,如果未能解决你的问题,请参考以下文章

java后台大数据量下的分批入库

mysql大数据量下优化

技术浅谈大数据量下数据库查询插入的优化

关于大数据量下进行大数据展示的杂谈

总结MySQL大数据量下如何进行优化

mysql在大数据量下性能调优相关参数