이 글에서는 동적 람다 표현식을 생성하기 위해 SqlDataReader를 주로 소개합니다. 필요한 친구는 이를 참조할 수 있습니다.
이전 기사에서는 동적 람다 표현식을 사용하여 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의 확장 메서드를 추가하려고 했지만 람다 식을 동적으로 생성하는 중에 오류가 발견되어 현재
솔루션을 먼저 기록했습니다.
위 내용은 ASP.NET의 SqlDataReader에 의해 생성된 동적 Lambda 표현식의 예에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!