zoukankan      html  css  js  c++  java
  • .Net工具类--表达式目录树解析DataReader和DataTable

    一、概述

         在项目中经常会使用SQL去操作数据库,在读取数据的时候返回结果一般是DataReader和DataSet,其中DataaSet里面可以包含多个DataTable。

    读取到数据之后,一般情况下,我们需要把DataReader和DataSet解析成另外的数据实体和数据集合,有人会选择反射、硬编码,这些都是解决方案,

    其实还有其他的解决方案,那就是表达式目录树。

    二、解析DataReader

        这个是生成表达式的方法。

            /// <summary>
            /// SqlDataReader生成表达式
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="reader"></param>
            /// <returns></returns>
            public static Func<SqlDataReader, T> ToExpression<T>(this SqlDataReader reader)
            {
                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());
                var expr = Expression.Lambda<Func<SqlDataReader, T>>(init, parameter).Compile();
                return expr;
            }

    调用,这个方法写的比较简陋,只写了获取单个数据行,有需要其他类型的可以扩展一下。

            public static T GetTById(List<SqlParameter> parameters)
            {
                try
                {
                    var model = Activator.CreateInstance<T>();
                    string sql = GetBasicQuerySql() + " WHERE Id = @Id";
                    
                    Console.WriteLine(sql);
                    SqlDataReader result = null;
                    SqlConn(sql, (reader) => { result = (SqlDataReader)reader; }, SqlType.GetModel, parameters);
                    if (result.Read())
                    {
                        Func<SqlDataReader, T> func = result.ToExpression<T>();
                        model = func(result);
                    }
                    return model;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }

    三、解析DataTable

      下面是解析DataTable的,可以直接调用,写的是DataTable的扩展方法,调用方式和ToString一样,就不举例了。

            /// <summary>
            /// DataTable生成实体
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="dataTable"></param>
            /// <returns></returns>
            public static List<T> ToList<T>(this DataTable dataTable)
            {
                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)
            {
                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();
            }

    学无止境,多积累,多实践。

  • 相关阅读:
    C++设计模式之享元模式
    C++设计模式之中介者模式
    C++设计模式之职责链模式
    C++设计模式之命令模式
    C++设计模式之桥接模式
    C++设计模式之单例模式
    C++设计模式之组合模式
    C++设计模式之备忘录模式
    C++设计模式之适配器模式
    操作系统(4)实验0——准备知识、基本内联汇编、扩展内联汇编
  • 原文地址:https://www.cnblogs.com/bobo-pcb/p/11634565.html
Copyright © 2011-2022 走看看