zoukankan      html  css  js  c++  java
  • 大数据量下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     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 }
    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反而比较快。

  • 相关阅读:
    模块:标准库Shelve
    模块:标准库shutil
    模块:标准库sys
    关于html中的文本节点问题
    MVVM
    iOS 检测有没有安装其它应用 和ios9下要注意的地方
    iOS9对SDK的影响(iOS9适配必看)
    CircleLayout
    MapSearch 阅读随笔
    苹果官网 demo The Elements 阅读随笔
  • 原文地址:https://www.cnblogs.com/LiuNew/p/10562041.html
Copyright © 2011-2022 走看看