• 生成动态Lambda表达式1


    SqlDataReader生成动态Lambda表达式

    上一扁使用动态lambda表达式来将DataTable转换成实体,比直接用反射快了不少。主要是首行转换的时候动态生成了委托。

    后面的转换都是直接调用委托,省去了多次用反射带来的性能损失。

    今天在对SqlServer返回的流对象 SqlDataReader 进行处理,也采用动态生成Lambda表达式的方式转换实体。

    先上一版代码

    复制代码
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Data;
     4 using System.Data.Common;
     5 using System.Data.SqlClient;
     6 using System.Linq;
     7 using System.Linq.Expressions;
     8 using System.Reflection;
     9 using System.Text;
    10 using System.Threading.Tasks;
    11 
    12 namespace Demo1
    13 {
    14     public static class EntityConverter
    15     {
    16         #region
    17         /// <summary>
    18         /// DataTable生成实体
    19         /// </summary>
    20         /// <typeparam name="T"></typeparam>
    21         /// <param name="dataTable"></param>
    22         /// <returns></returns>
    23         public static List<T> ToList<T>(this DataTable dataTable) where T : class, new()
    24         {
    25             if (dataTable == null || dataTable.Rows.Count <= 0) throw new ArgumentNullException("dataTable", "当前对象为null无法生成表达式树");
    26             Func<DataRow, T> func = dataTable.Rows[0].ToExpression<T>();
    27             List<T> collection = new List<T>(dataTable.Rows.Count);
    28             foreach (DataRow dr in dataTable.Rows)
    29             {
    30                 collection.Add(func(dr));
    31             }
    32             return collection;
    33         }
    34 
    35       
    36         /// <summary>
    37         /// 生成表达式
    38         /// </summary>
    39         /// <typeparam name="T"></typeparam>
    40         /// <param name="dataRow"></param>
    41         /// <returns></returns>
    42         public static Func<DataRow, T> ToExpression<T>(this DataRow dataRow) where T : class, new()
    43         {
    44             if (dataRow == null) throw new ArgumentNullException("dataRow", "当前对象为null 无法转换成实体");
    45             ParameterExpression parameter = Expression.Parameter(typeof(DataRow), "dr");
    46             List<MemberBinding> binds = new List<MemberBinding>();
    47             for (int i = 0; i < dataRow.ItemArray.Length; i++)
    48             {
    49                 String colName = dataRow.Table.Columns[i].ColumnName;
    50                 PropertyInfo pInfo = typeof(T).GetProperty(colName);
    51                 if (pInfo == null || !pInfo.CanWrite) continue;
    52                 MethodInfo mInfo = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(String) }).MakeGenericMethod(pInfo.PropertyType);
    53                 MethodCallExpression call = Expression.Call(mInfo, parameter, Expression.Constant(colName, typeof(String)));
    54                 MemberAssignment bind = Expression.Bind(pInfo, call);
    55                 binds.Add(bind);
    56             }
    57             MemberInitExpression init = Expression.MemberInit(Expression.New(typeof(T)), binds.ToArray());
    58             return Expression.Lambda<Func<DataRow, T>>(init, parameter).Compile();
    59         }
    60         #endregion
    61         /// <summary>
    62         /// 生成lambda表达式
    63         /// </summary>
    64         /// <typeparam name="T"></typeparam>
    65         /// <param name="reader"></param>
    66         /// <returns></returns>
    67         public static Func<SqlDataReader, T> ToExpression<T>(this SqlDataReader reader) where T : class, new()
    68         {
    69             if (reader == null || reader.IsClosed || !reader.HasRows) throw new ArgumentException("reader", "当前对象无效");
    70             ParameterExpression parameter = Expression.Parameter(typeof(SqlDataReader), "reader");
    71             List<MemberBinding> binds = new List<MemberBinding>();
    72             for (int i = 0; i < reader.FieldCount; i++)
    73             {
    74                 String colName = reader.GetName(i);
    75                 PropertyInfo pInfo = typeof(T).GetProperty(colName);
    76                 if (pInfo == null || !pInfo.CanWrite) continue;
    77                 MethodInfo mInfo = reader.GetType().GetMethod("GetFieldValue").MakeGenericMethod(pInfo.PropertyType);
    78                 MethodCallExpression call = Expression.Call(parameter, mInfo, Expression.Constant(i));
    79                 MemberAssignment bind = Expression.Bind(pInfo, call);
    80                 binds.Add(bind);
    81             }
    82             MemberInitExpression init = Expression.MemberInit(Expression.New(typeof(T)), binds.ToArray());
    83             return Expression.Lambda<Func<SqlDataReader, T>>(init, parameter).Compile();
    84         }
    85 
    86     }
    87 }
    复制代码

    在上一篇的基础上增加了 SqlDataReader 的扩展方法

    以下代码是调用

    复制代码
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Data;
     4 using System.Data.Common;
     5 using System.Data.SqlClient;
     6 using System.Diagnostics;
     7 using System.Linq;
     8 using System.Reflection;
     9 using System.Text;
    10 using System.Threading.Tasks;
    11 
    12 namespace Demo1
    13 {
    14     class Program
    15     {
    16         static void Main(string[] args)
    17         {
    18             String conString = "Data Source=.; Initial Catalog=master; Integrated Security=true;";
    19             Func<SqlDataReader, Usr> func = null;
    20             List<Usr> usrs = new List<Usr>();
    21             using (SqlDataReader reader = GetReader(conString, "select object_id 'ID',name 'Name' from sys.objects", CommandType.Text, null))
    22             {
    23                 while (reader.Read())
    24                 {
    25                     if (func == null)
    26                     {
    27                         func = reader.ToExpression<Usr>();
    28                     }
    29                     Usr usr = func(reader);
    30                     usrs.Add(usr);
    31                 }
    32             }
    33             usrs.Clear();
    34             Console.ReadKey();
    35         }
    36 
    37         public static SqlDataReader GetReader(String conString, String sql, CommandType type, params SqlParameter[] pms)
    38         {
    39             SqlConnection conn = new SqlConnection(conString);
    40             SqlCommand cmd = new SqlCommand(sql, conn);
    41             cmd.CommandType = type;
    42             if (pms != null && pms.Count() > 0)
    43             {
    44                 cmd.Parameters.AddRange(pms);
    45             }
    46             conn.Open();
    47             return cmd.ExecuteReader(CommandBehavior.CloseConnection);
    48         }
    49     }
    50     class Usr
    51     {
    52         public Int32 ID { get; set; }
    53         public String Name { get; set; }
    54     }
    55 
    56 
    57 }
    复制代码

    目前只能处理sqlserver返回的对象,处理其它数据库本来是想增加 DbDataReader 的扩展方法,但发现动态生成lambda表达式的地方出错,所以先将现在的

  • 相关阅读:
    .net Winform 32位桌面应用程序突破系统2G内存限制,解决内存溢出问题
    .Net Core WebAPI Swagger Failed to load API definition
    MySql 安装详细步骤
    Vue ElementUI 按需引入提示Cannot find module 'babelpresetes2015'
    复制label标签上的文本
    3D游戏的碰撞检测是如何实现的?
    flex布局定位二
    flex布局定位一
    k8s工作负载、服务、pod
    应用内moniter
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/6731636.html
Copyright © 2020-2023  润新知