DataTable 转实体
发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,因为Linq的查询功能很强大,所以从数据库中拿到的数据为了处理方便,我都会转换成实体集合List。开始用的是硬编码的方式,好理解,但通用性极低,下面是控件台中的代码: 1 using System;
千家信息网最后更新 2025年02月01日DataTable 转实体
因为Linq的查询功能很强大,所以从数据库中拿到的数据为了处理方便,我都会转换成实体集合List
开始用的是硬编码的方式,好理解,但通用性极低,下面是控件台中的代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Data; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace Demo1 9 {10 class Program11 {12 static void Main(string[] args)13 {14 DataTable dt = Query();15 Listusrs = new List (dt.Rows.Count);16 //硬编码,效率比较高,但灵活性不够,如果实体改变了,都需要修改代码17 foreach (DataRow dr in dt.Rows)18 {19 Usr usr = new Usr { ID = dr.Field ("ID"), Name = dr.Field ("Name") };20 usrs.Add(usr);21 }22 usrs.Clear();23 }24 25 /// 26 /// 查询数据27 /// 28 ///29 private static DataTable Query()30 {31 DataTable dt = new DataTable();32 dt.Columns.Add("ID", typeof(Int32));33 dt.Columns.Add("Name", typeof(String));34 for (int i = 0; i < 1000000; i++)35 {36 dt.Rows.Add(new Object[] { i, Guid.NewGuid().ToString() });37 }38 return dt;39 }40 }41 class Usr42 {43 public Int32? ID { get; set; }44 public String Name { get; set; }45 }46 }
后来用反射来做这,对实体的属性用反射去赋值,这样就可以对所有的实体通用,且增加属性后不用修改代码。
程序如下:
1 static class EntityConvert 2 { 3 ///4 /// DataTable转为List 6 ///5 /// 7 /// 8 /// 9 public static List ToList (this DataTable dt) where T : class, new()10 {11 List colletion = new List ();12 PropertyInfo[] pInfos = typeof(T).GetProperties();13 foreach (DataRow dr in dt.Rows)14 {15 T t = new T();16 foreach (PropertyInfo pInfo in pInfos)17 {18 if (!pInfo.CanWrite) continue;19 pInfo.SetValue(t, dr[pInfo.Name]);20 }21 colletion.Add(t);22 }23 return colletion;24 }25 }
增加一个扩展方法,程序更加通用。但效率不怎么样,100万行数据【只有两列】,转换需要2秒
后来想到用委托去做 委托原型如下
1 Funcfunc = dr => new Usr { ID = dr.Field ("ID"), Name = dr.Field ("Name") };
代码如下:
1 static void Main(string[] args) 2 { 3 DataTable dt = Query(); 4 Funcfunc = dr => new Usr { ID = dr.Field ("ID"), Name = dr.Field ("Name") }; 5 List usrs = new List (dt.Rows.Count); 6 Stopwatch sw = Stopwatch.StartNew(); 7 foreach (DataRow dr in dt.Rows) 8 { 9 Usr usr = func(dr);10 usrs.Add(usr);11 }12 sw.Stop();13 Console.WriteLine(sw.ElapsedMilliseconds);14 usrs.Clear();15 Console.ReadKey();16 }
速度确实快了很多,我电脑测试了一下,需要 0.4秒。但问题又来了,这个只能用于Usr这个类,得想办法把这个类抽象成泛型T,既有委托的高效,又有
泛型的通用。
问题就在动态地产生上面的委托了,经过一下午的折腾终于折腾出来了动态产生委托的方法。主要用到了动态Lambda表达式
1 public static class EntityConverter 2 { 3 ///4 /// DataTable生成实体 5 /// 6 ///7 /// 8 /// 9 public static List ToList (this DataTable dataTable) where T : class, new()10 {11 if (dataTable == null || dataTable.Rows.Count <= 0) throw new ArgumentNullException("dataTable", "当前对象为null无法生成表达式树");12 Func func = dataTable.Rows[0].ToExpression ();13 List collection = new List (dataTable.Rows.Count);14 foreach (DataRow dr in dataTable.Rows)15 {16 collection.Add(func(dr));17 }18 return collection;19 }20 21 /// 22 /// 生成表达式23 /// 24 ///25 /// 26 /// 27 public static Func ToExpression (this DataRow dataRow) where T : class, new()28 {29 if (dataRow == null) throw new ArgumentNullException("dataRow", "当前对象为null 无法转换成实体");30 ParameterExpression paramter = Expression.Parameter(typeof(DataRow), "dr");31 List binds = new List ();32 for (int i = 0; i < dataRow.ItemArray.Length; i++)33 {34 String colName = dataRow.Table.Columns[i].ColumnName;35 PropertyInfo pInfo = typeof(T).GetProperty(colName);36 if (pInfo == null) continue;37 MethodInfo mInfo = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(String) }).MakeGenericMethod(pInfo.PropertyType);38 MethodCallExpression call = Expression.Call(mInfo, paramter, Expression.Constant(colName, typeof(String)));39 MemberAssignment bind = Expression.Bind(pInfo, call);40 binds.Add(bind);41 }42 MemberInitExpression init = Expression.MemberInit(Expression.New(typeof(T)), binds.ToArray());43 return Expression.Lambda >(init, paramter).Compile();44 }45 }
经过测试,用这个方法在同样的条件下转换实体需要 0.47秒。除了第一次用反射生成Lambda表达式外,后续的转换直接用的表达式。
实体
表达式
委托
代码
数据
生成
动态
方法
反射
对象
属性
效率
程序
编码
问题
查询
测试
强大
不怎么样
不够
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
网吧服务器可以放地下室吗
ns更新后暗黑2无法连接服务器
阿尔德里奇数据库
松江区市场软件开发大概费用
ibm服务器read管理
计算机网络技术评价总结
光遇体验服现在服务器正常吗
舟山软件开发找哪家
cms数据库地址
网络技术防水施工
天弘互联网绩优科技
在线调查研究的先进网络技术有
在数据库查询业务ip
学生信息系统数据库语句
塔石485串口服务器设置
武汉短视频云控软件开发商
小型河南软件开发公司有哪些
数据库工程师考试真题与答案
服务器机柜深1200
中学生网络安全游戏
库里连接数据库
ins刷粉软件开发
数据库建表字段值怎么写
网络安全宣传周学校在行动
华为商店连不上服务器怎么解决
江苏有多少台服务器
第七届首都网络安全日征文
数据库的技术系统
服装销售 数据库设计
信息网络安全 考试