.Net工具類--表達式目錄樹解析DataReader和DataTable

1、概述

     在項目中常常會使用SQL去操做數據庫,在讀取數據的時候返回結果通常是DataReader和DataSet,其中DataaSet裏面能夠包含多個DataTable。sql

讀取到數據以後,通常狀況下,咱們須要把DataReader和DataSet解析成另外的數據實體和數據集合,有人會選擇反射、硬編碼,這些都是解決方案,數據庫

其實還有其餘的解決方案,那就是表達式目錄樹。this

2、解析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;
        }

調用,這個方法寫的比較簡陋,只寫了獲取單個數據行,有須要其餘類型的能夠擴展一下。spa

        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;
            }
        }

3、解析DataTable

  下面是解析DataTable的,能夠直接調用,寫的是DataTable的擴展方法,調用方式和ToString同樣,就不舉例了。code

        /// <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();
        }

學無止境,多積累,多實踐。對象

相關文章
相關標籤/搜索