zoukankan      html  css  js  c++  java
  • 【原】超简单类型转换(DataTable > List/JSON)的实现

    背景:

    开发工作中经常需要类型的转换,比如DataTable转换为List、或是DataTable转换为JSON等等,

    每次都重复的写相同的代码,比如:把实体类的字段属性一个一个的列出来,从DataTabel中把值取出来赋上,

    真的好麻烦 (*=*)

    思考:

    1)DataTable转换为List,主要是使用反射,遍历实体类的属性,和DataTabel中的列进行对比并赋值

    2)DataTable转换为JSON,主要是拼接JSON串

    实践:

    参考了网上很多前辈的思路和实现,制作了一个ConvertHelper类,感谢各位前辈 ^_^

    转换辅助类ConvertHelper代码如下,覆盖范围包括属性和公共字段:

    ConvertHelper
      1 /// <summary>
      2 /// 转换辅助类
      3 /// </summary>
      4 /// <typeparam name="T"></typeparam>
      5 public class ConvertHelper<T> where T : new()
      6 {
      7     /// <summary>
      8     /// DataTable-->List
      9     /// </summary>
     10     /// <param name="dt">DataTable</param>
     11     /// <returns></returns>
     12     public static IList<T> DataTableConvertToList(DataTable dt)
     13     {
     14         IList<T> ts = new List<T>();
     15 
     16         // 取得泛型的类型
     17         Type type = typeof(T);
     18 
     19         // 创建类型的对象(用于比较用)
     20         //object convertObj = Activator.CreateInstance(type, null);
     21 
     22         // 反射取得类型实例的属性数组
     23         //PropertyInfo[] propertys = convertObj.GetType().GetProperties();
     24         PropertyInfo[] propertys = type.GetProperties();
     25 
     26         // 反射取得类型实例的字段数组
     27         FieldInfo[] fields = type.GetFields();
     28 
     29         foreach (DataRow dr in dt.Rows)
     30         {
     31             // 创建类型的对象(用于赋值用)
     32             //object outputObj = Activator.CreateInstance(type, null);
     33             T outputObj = new T();
     34 
     35             // 遍历字段(公共字段)
     36             foreach (FieldInfo fi in fields)
     37             {
     38                 // 如果DataTable的数据列中包含有对应的字段
     39                 if (dt.Columns.Contains(fi.Name))
     40                 {
     41                     // 取得字段的值
     42                     object value = dr[fi.Name];
     43 
     44                     if (value != DBNull.Value)
     45                     {
     46                         // 将对应字段的值赋给创建的类型实例的对应的字段
     47                         fi.SetValue(outputObj, value);
     48                     }
     49                 }
     50             }
     51 
     52             // 遍历属性
     53             foreach (PropertyInfo pi in propertys)
     54             {
     55                 // 如果DataTable的数据列中包含有对应的属性
     56                 if (dt.Columns.Contains(pi.Name))
     57                 {
     58                     if (!pi.CanWrite)
     59                     {
     60                         continue;
     61                     }
     62 
     63                     // 取得属性的值
     64                     object value = dr[pi.Name];
     65 
     66                     if (value != DBNull.Value)
     67                     {
     68                         // 将对应属性的值赋给创建的类型实例的对应的属性
     69                         pi.SetValue(outputObj, value, null);
     70                     }
     71                 }
     72             }
     73 
     74             // 添加到List中
     75             ts.Add((T)outputObj);
     76         }
     77 
     78         return ts;
     79     }
     80 
     81     /// <summary>
     82     /// DataTable-->Json
     83     /// </summary>
     84     /// <param name="dt">DataTable</param>
     85     /// <returns></returns>
     86     public static string DataTableConvertToJson(DataTable dt)
     87     {
     88         StringBuilder jsonBuilder = new StringBuilder();
     89 
     90         // 拼接JSON串
     91         jsonBuilder.Append("{\"");
     92         jsonBuilder.Append(dt.TableName);
     93         jsonBuilder.Append("\":[");
     94         for (int i = 0; i < dt.Rows.Count; i++)
     95         {
     96             jsonBuilder.Append("{");
     97             for (int j = 0; j < dt.Columns.Count; j++)
     98             {
     99                 jsonBuilder.Append("\"");
    100                 jsonBuilder.Append(dt.Columns[j].ColumnName);
    101                 jsonBuilder.Append("\":\"");
    102                 jsonBuilder.Append(dt.Rows[i][j].ToString());
    103                 jsonBuilder.Append("\",");
    104             }
    105             jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
    106             jsonBuilder.Append("},");
    107         }
    108         jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
    109         jsonBuilder.Append("]");
    110         jsonBuilder.Append("}");
    111 
    112         return jsonBuilder.ToString();
    113     }
    114 
    115     /// <summary>
    116     /// DataSet-->Json
    117     /// </summary>
    118     /// <param name="ds">DataSet</param>
    119     /// <returns></returns>
    120     public static string DataSetConvertToJson(DataSet ds)
    121     {
    122         StringBuilder json = new StringBuilder();
    123 
    124         foreach (DataTable dt in ds.Tables)
    125         {
    126             // 拼接JSON串
    127             json.Append("{\"");
    128             json.Append(dt.TableName);
    129             json.Append("\":");
    130             json.Append(DataTableConvertToJson(dt));
    131             json.Append("}");
    132         }
    133         
    134         return json.ToString();
    135     }
    136 }

    如何使用呢?

    很方便的,先定义一个实体类UserInfo,定义了13个字段

    UserInfo
     1 /// <summary>
     2 /// 用户信息实体
     3 /// </summary>
     4 public class UserInfo
     5 {
     6     /// <summary>
     7     /// 用户编号
     8     /// </summary>
     9     public int UserID { get; set; }
    10 
    11     /// <summary>
    12     /// 用户姓名
    13     /// </summary>
    14     public string UserName { get; set; }
    15 
    16     /// <summary>
    17     /// 性别
    18     /// </summary>
    19     public string Gender { get; set; }
    20 
    21     /// <summary>
    22     /// 身高
    23     /// </summary>
    24     public decimal Height { get; set; }
    25 
    26     /// <summary>
    27     /// 体重
    28     /// </summary>
    29     public decimal Weight { get; set; }
    30 
    31     /// <summary>
    32     /// 生日
    33     /// </summary>
    34     public DateTime Birthday { get; set; }
    35 
    36     /// <summary>
    37     /// 出生地
    38     /// </summary>
    39     public string HomeTown { get; set; }
    40 
    41     /// <summary>
    42     /// 部门
    43     /// </summary>
    44     public string Department { get; set; }
    45 
    46     /// <summary>
    47     /// 职级
    48     /// </summary>
    49     public string Level { get; set; }
    50 
    51     /// <summary>
    52     /// 用户薪资
    53     /// </summary>
    54     public decimal Salary { get; set; }
    55 
    56     /// <summary>
    57     /// 爱好
    58     /// </summary>
    59     public string Hobby { get; set; }
    60 
    61     /// <summary>
    62     /// 学历
    63     /// </summary>
    64     public string Degress = string.Empty;
    65 
    66     /// <summary>
    67     /// 年龄
    68     /// </summary>
    69     public int Age = 0;
    70 }

    再定义一个方法填充一些数据模拟DataTable,这里填充了50w条记录

    MockData
     1 /// <summary>
     2 /// 模拟数据
     3 /// </summary>
     4 /// <returns></returns>
     5 private static DataTable MockData()
     6 {
     7     DataTable dt = new DataTable("UserInfo");
     8 
     9     // 添加数据列
    10     DataColumn dc = null;
    11 
    12     dc = dt.Columns.Add("UserID", Type.GetType("System.Int32"));
    13     dc.AutoIncrement = true;    //自动增加
    14     dc.AutoIncrementSeed = 1;   //起始为1
    15     dc.AutoIncrementStep = 1;   //步长为1
    16     dc.AllowDBNull = false;
    17 
    18     dc = dt.Columns.Add("UserName", Type.GetType("System.String"));
    19     dc = dt.Columns.Add("Gender", Type.GetType("System.String"));
    20     dc = dt.Columns.Add("Height", Type.GetType("System.Decimal"));
    21     dc = dt.Columns.Add("Weight", Type.GetType("System.Decimal"));
    22     dc = dt.Columns.Add("Birthday", Type.GetType("System.DateTime"));
    23     dc = dt.Columns.Add("HomeTown", Type.GetType("System.String"));
    24     dc = dt.Columns.Add("Department", Type.GetType("System.String"));
    25     dc = dt.Columns.Add("Level", Type.GetType("System.String"));
    26     dc = dt.Columns.Add("Salary", Type.GetType("System.Decimal"));
    27     dc = dt.Columns.Add("Hobby", Type.GetType("System.String"));
    28     dc = dt.Columns.Add("Degress", Type.GetType("System.String"));
    29     dc = dt.Columns.Add("Age", Type.GetType("System.Int32"));
    30 
    31 
    32     #region 添加数据行
    33 
    34     // 方式1
    35     //DataRow dr = null;
    36 
    37     //dr = dt.NewRow();
    38     //dr["UserName"] = "洪自军";
    39     //dr["Salary"] = 123.45;
    40     //dt.Rows.Add(dr);
    41 
    42     //dr = dt.NewRow();
    43     //dr["UserName"] = "武建昌";
    44     //dr["Salary"] = 987.65;
    45     //dt.Rows.Add(dr);
    46 
    47     // 方式2
    48     //dt.Rows.Add(new object[] { null, "張洋", 123.45 });
    49     //dt.Rows.Add(new object[] { null, "張兄家", 987.65 });
    50     //dt.Rows.Add(new object[] { null, "王生杰", 111.11 });
    51     //dt.Rows.Add(new object[] { null, "呉QQ", 888.88 });
    52     //dt.Rows.Add(new object[] { null, "劉瑞", 222.22 });
    53 
    54     for (int i = 0; i < 500000; i++)
    55     {
    56         dt.Rows.Add(new object[] { 
    57             null, "测试" + i, "", 123.45, 543.21,
    58             "1990-02-14", "火星", "码农组", "码农", 250.13, "吃喝玩乐",
    59             1127963, 20
    60         });
    61     }
    62 
    63     #endregion
    64 
    65     return dt;
    66 }

    调用转换辅助类进行转换

    调用转换处理
     1 /// <summary>
     2 /// DataTable-->List测试
     3 /// </summary>
     4 private static void MockDataTableConvertToList()
     5 {
     6     // 定义时间起点
     7     TimeSpan tsStart = new TimeSpan(DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);
     8 
     9     // 変換処理
    10     IList<UserInfo> users = ConvertHelper<UserInfo>.DataTableConvertToList(MockData());
    11 
    12     // 定义时间终点
    13     TimeSpan tsEnd = new TimeSpan(DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);
    14 
    15     // 计算耗时
    16     TimeSpan ts = tsStart.Subtract(tsEnd).Duration();
    17 
    18     Console.WriteLine(string.Format("DataTable-->List 変換耗時:{0}", ts.ToString()));
    19 
    20     //foreach (var user in users)
    21     //{
    22     //    Console.WriteLine("{0} : {1} - {2};", user.UserID, user.UserName, user.Salary);
    23     //}
    24 }
    25 
    26 /// <summary>
    27 /// DataTable-->Json测试
    28 /// </summary>
    29 private static void MockDataTableConvertToJson()
    30 {
    31     // 定义时间起点
    32     TimeSpan tsStart = new TimeSpan(DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);
    33 
    34     // 変換処理
    35     string jsonString = ConvertHelper<UserInfo>.DataTableConvertToJson(MockData());
    36 
    37     // 定义时间终点
    38     TimeSpan tsEnd = new TimeSpan(DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);
    39 
    40     // 计算耗时
    41     TimeSpan ts = tsStart.Subtract(tsEnd).Duration();
    42 
    43     Console.WriteLine(string.Format("DataTable-->Json 変換耗時:{0}", ts.ToString()));
    44 
    45     //Console.WriteLine(jsonString);
    46 }

    两句代码完成

    IList<UserInfo> users = ConvertHelper<UserInfo>.DataTableConvertToList(MockData());
    
    string jsonString = ConvertHelper<UserInfo>.DataTableConvertToJson(MockData());

    可以看到转换后的效果

    前几条数据是DataTable转换为List的效果,后一条数据是DataTable转换为JSON的效果

    再贴一张类型转换时间的测试结果吧,50w条记录转换10秒左右

    是不是很简单呢?

    如果您有好的实现或是意见,别忘了告诉我哦 ^_^

  • 相关阅读:
    zookeeper使用场景
    zookeeper安装配置
    hadoop 远程调试
    deep learning笔记
    Sentiment Analysis(1)-Dependency Tree-based Sentiment Classification using CRFs with Hidden Variables
    PRML阅读笔记 introduction
    Python 学习笔记(2)
    python nltk 学习笔记(5) Learning to Classify Text
    python nltk 学习笔记(4) Writing Structured Programs
    python nltk 学习笔记(3) processing raw text
  • 原文地址:https://www.cnblogs.com/iflytek/p/2764591.html
Copyright © 2011-2022 走看看