.Net工具类--表达式目录树解析DataReader和DataTable

Posted bobo-pcb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.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();
        

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

 

以上是关于.Net工具类--表达式目录树解析DataReader和DataTable的主要内容,如果未能解决你的问题,请参考以下文章

表达式目录树的扩展

Atitit.sql ast 表达式 语法树 语法 解析原理与实现 java php c#.net js

在表达式树中实现 Not,.net 4

.net 常用工具类收藏

通过正则表达式实现简单xml文件解析

Lambda 表达式树解析