背景:
开发工作中经常需要类型的转换,比如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秒左右
是不是很简单呢?
如果您有好的实现或是意见,别忘了告诉我哦 ^_^