VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > .net教程 >
  • ASP.net教程之大数据量下DataTable To List效率对比

 

反射将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     T t = new T();
 6     PropertyInfo[] propertys = t.GetType().GetProperties();
 7     foreach (DataRow dr in dt.Rows)
 8     {
 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反而比较快。

相关教程