In diesem Artikel wird hauptsächlich SqlDataReader zum Generieren dynamischer Lambda-Ausdrücke vorgestellt.
Der vorherige Artikel verwendet dynamische Lambda-Ausdrücke, um DataTable in Entitäten umzuwandeln. Dies ist viel schneller als die direkte Verwendung von Reflektion. wenige. Der Hauptgrund liegt darin, dass die Provision dynamisch generiert wird, wenn die erste Zeile konvertiert wird.
Die nachfolgenden Konvertierungen rufen alle den Delegaten direkt auf, wodurch der durch Mehrfachreflexionen verursachte Leistungsverlust vermieden wird.
Heute verarbeite ich das von SqlServer zurückgegebene Stream-Objekt SqlDataReader und konvertiere auch Entitäten durch dynamische Generierung von Lambda-Ausdrücken.
Erste Version des Codes
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(); } } }
Basierend auf dem vorherigen Artikel wurde die Erweiterungsmethode von SqlDataReader hinzugefügt
Der folgende Code heißt
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; } } }
Derzeit können wir nur von SQL Server zurückgegebene Objekte verarbeiten. Beim Umgang mit anderen Datenbanken wollten wir ursprünglich die Erweiterungsmethode von DbDataReader hinzufügen, aber wir haben einen Fehler beim dynamischen Generieren von Lambda-Ausdrücken festgestellt, also haben wir zuerst den aktuellen
planen.Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung von Beispielen dynamischer Lambda-Ausdrücke, die von SqlDataReader in ASP.NET generiert werden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!