DataTable 转实体
发表于:2024-10-23 作者:千家信息网编辑
千家信息网最后更新 2024年10月23日,因为Linq的查询功能很强大,所以从数据库中拿到的数据为了处理方便,我都会转换成实体集合List。开始用的是硬编码的方式,好理解,但通用性极低,下面是控件台中的代码: 1 using System;
千家信息网最后更新 2024年10月23日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安全错误
数据库的锁怎样保障安全
松下网络技术有限公司招聘
数据库的存储过程怎么写
学术文件数据库的特点
汉鼎宇佑互联网科技有限公司
关系数据库一对多关系怎么确定
曙光服务器web管理功能
东营联想服务器代理经销商
计算机网络技术属于电子类么
网络安全宣传周主旨
武汉维天网络技术有限公司
网络安全问题备受大咖关注
可能该数据库尚未激活 也可能
数据库悲观锁的使用
4g软件开发工程大专
云服务器 数据库外网访问
网络安全举报之后如何受理
为什么独立服务器比较好
义乌网络安全事件
国家网络安全宣传书签
东阳市天气预报软件开发
本科网络安全专业
北京零彩宝网络技术怎么样
城乡规划数据库汇交
泰州服务器工控机驱动
hps软件开发流程
4g软件开发工程大专
网络安全20讲
全球服务器手机版
武汉无为广域网络技术
中国5g网络技术图片