SqlDataReader生成动态Lambda表达式
程序员文章站
2023-11-25 13:16:34
使用动态lambda表达式来将datatable转换成实体,比直接用反射快了不少。主要是首行转换的时候动态生成了委托。
后面的转换都是直接调用委托,省去了多次用反射带来的...
使用动态lambda表达式来将datatable转换成实体,比直接用反射快了不少。主要是首行转换的时候动态生成了委托。
后面的转换都是直接调用委托,省去了多次用反射带来的性能损失。
今天在对sqlserver返回的流对象 sqldatareader 进行处理,也采用动态生成lambda表达式的方式转换实体。
先上一版代码
using system; using system.collections.generic; using system.data; using system.data.common; using system.data.sqlclient; using system.linq; using system.linq.expressions; using system.reflection; using system.text; using system.threading.tasks; namespace demo1 { public static class entityconverter { #region /// <summary> /// datatable生成实体 /// </summary> /// <typeparam name="t"></typeparam> /// <param name="datatable"></param> /// <returns></returns> public static list<t> tolist<t>(this datatable datatable) where t : class, new() { if (datatable == null || datatable.rows.count <= 0) throw new argumentnullexception("datatable", "当前对象为null无法生成表达式树"); func<datarow, t> func = datatable.rows[0].toexpression<t>(); list<t> collection = new list<t>(datatable.rows.count); foreach (datarow dr in datatable.rows) { collection.add(func(dr)); } return collection; } /// <summary> /// 生成表达式 /// </summary> /// <typeparam name="t"></typeparam> /// <param name="datarow"></param> /// <returns></returns> public static func<datarow, t> toexpression<t>(this datarow datarow) where t : class, new() { if (datarow == null) throw new argumentnullexception("datarow", "当前对象为null 无法转换成实体"); parameterexpression parameter = expression.parameter(typeof(datarow), "dr"); list<memberbinding> binds = new list<memberbinding>(); for (int i = 0; i < datarow.itemarray.length; i++) { string colname = datarow.table.columns[i].columnname; propertyinfo pinfo = typeof(t).getproperty(colname); if (pinfo == null || !pinfo.canwrite) continue; methodinfo minfo = typeof(datarowextensions).getmethod("field", new type[] { typeof(datarow), typeof(string) }).makegenericmethod(pinfo.propertytype); methodcallexpression call = expression.call(minfo, parameter, expression.constant(colname, typeof(string))); memberassignment bind = expression.bind(pinfo, call); binds.add(bind); } memberinitexpression init = expression.memberinit(expression.new(typeof(t)), binds.toarray()); return expression.lambda<func<datarow, t>>(init, parameter).compile(); } #endregion /// <summary> /// 生成lambda表达式 /// </summary> /// <typeparam name="t"></typeparam> /// <param name="reader"></param> /// <returns></returns> public static func<sqldatareader, t> toexpression<t>(this sqldatareader reader) where t : class, new() { if (reader == null || reader.isclosed || !reader.hasrows) throw new argumentexception("reader", "当前对象无效"); parameterexpression parameter = expression.parameter(typeof(sqldatareader), "reader"); list<memberbinding> binds = new list<memberbinding>(); for (int i = 0; i < reader.fieldcount; i++) { string colname = reader.getname(i); propertyinfo pinfo = typeof(t).getproperty(colname); if (pinfo == null || !pinfo.canwrite) continue; methodinfo minfo = reader.gettype().getmethod("getfieldvalue").makegenericmethod(pinfo.propertytype); methodcallexpression call = expression.call(parameter, minfo, expression.constant(i)); memberassignment bind = expression.bind(pinfo, call); binds.add(bind); } memberinitexpression init = expression.memberinit(expression.new(typeof(t)), binds.toarray()); return expression.lambda<func<sqldatareader, t>>(init, parameter).compile(); } } }
在上一篇的基础上增加了 sqldatareader 的扩展方法
以下代码是调用
using system; using system.collections.generic; using system.data; using system.data.common; using system.data.sqlclient; using system.diagnostics; using system.linq; using system.reflection; using system.text; using system.threading.tasks; namespace demo1 { class program { static void main(string[] args) { string constring = "data source=.; initial catalog=master; integrated security=true;"; func<sqldatareader, usr> func = null; list<usr> usrs = new list<usr>(); using (sqldatareader reader = getreader(constring, "select object_id 'id',name 'name' from sys.objects", commandtype.text, null)) { while (reader.read()) { if (func == null) { func = reader.toexpression<usr>(); } usr usr = func(reader); usrs.add(usr); } } usrs.clear(); console.readkey(); } public static sqldatareader getreader(string constring, string sql, commandtype type, params sqlparameter[] pms) { sqlconnection conn = new sqlconnection(constring); sqlcommand cmd = new sqlcommand(sql, conn); cmd.commandtype = type; if (pms != null && pms.count() > 0) { cmd.parameters.addrange(pms); } conn.open(); return cmd.executereader(commandbehavior.closeconnection); } } class usr { public int32 id { get; set; } public string name { get; set; } } }
目前只能处理sqlserver返回的对象,处理其它数据库本来是想增加 dbdatareader 的扩展方法,但发现动态生成lambda表达式的地方出错,所以先将现在的
方案记录下来。
推荐阅读
-
动态构建Lambda表达式实现EF动态查询
-
SqlDataReader生成动态Lambda表达式
-
SqlDataReader生成动态Lambda表达式
-
动态构建Lambda表达式实现EF动态查询
-
在EF中使用Expression自动生成p=>new Entity(){X="",Y="",..}格式的Lambda表达式灵活实现按需更新
-
Python爬虫与数据分析之进阶教程:文件操作、lambda表达式、递归、yield生成器
-
C# 表达式树 创建、生成、使用、lambda转成表达式树~表达式树的知识详解
-
[Java笔记]动态代理、lambda表达式、函数式接口、构造器引用
-
在EF中使用Expression自动生成p=>new Entity(){X="",Y="",..}格式的Lambda表达式灵活实现按需更新
-
ASP.NET中SqlDataReader生成动态Lambda表达式的实例详解