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

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

原文地址:https://www.cnblogs.com/bobo-pcb/p/11634565.html

时间: 2024-11-05 15:56:48

.Net工具类--表达式目录树解析DataReader和DataTable的相关文章

dnspy的详细配置,dnspy如何过滤反编译之后的乱码,dnspy如何反编译表达式目录树

dnSpy应该是目前使用最多的.net反编译工具.很多情况下反编译C#代码非常方便,特别是查找基类,子类.搜索一些class,方法.接口,非常方便.比ILspy好很多.而且dnspy是可以配置的. 如果要dnSpy非常干净地显示反编译之后的代码,可以看我具体的配置: 第一张是效果图,过滤一个具体的关键词筛选的时候可以使用[全词匹配],可以在所有的.net framework中查找你需要寻找的那个关键字,不区分大小写. 右侧底部的这个搜索框是可以配置的,而且有时候很容易被隐藏掉,需要"上拉&quo

表达式目录树Expression

表达式目录树是用于动态的linq语句的拼装在以前遇到数据筛选的情况下我们日常的操作是 1 Console.WriteLine("输入Name 不写为空"); 2 var name = Console.ReadLine(); 3 Console.WriteLine("输入PassWord 不写为空"); 4 var PassWord = Console.ReadLine(); 5 string sql = "select * from Student whe

第十九节: 结合【表达式目录树】来封装EF的BaseDal层的方法

一. 简介 该章节,可以说是一个简单轻松的章节,只要你对Expression表达式树.EF的基本使用.泛型有所了解,那么本章节实质上就是一个非常简单的封装章节,便于我们快捷开发. PS:在该章节对于EF的DB上下文怎么处理,怎么来的,不做介绍,在后续的框架篇将详细介绍. 如果你对Expression.EF的增删改查.泛型生疏的话,可以先阅读以下章节: (1). Expression表达式目录树:http://www.cnblogs.com/yaopengfei/p/7486870.html (2

Lambda创建表达式目录树

一,如下代码: using System; using System.Linq.Expressions; namespace Demo { class Program { static void Main(string[] args) { Func<int, int, int> func = null; //两个参数 ParameterExpression a = Expression.Parameter(typeof(int), "a"); ParameterExpres

JAVA File类 打印目录树状结构图 递归算法

  要实现把制定目录下的所有文件,按照树状结构打印出来的目的. 代码如下: package cn.bjsxt.io; import java.io.File; public class FileTree {        public static void main(String[] args) {                File f=new File("E:/有用的文档"); //假设打印这个目录下的所有文件                printTree(f, 0);

通过表达式目录树拼装lambda表达式,来实现两个类型的复制

一.下面的方法实现两个类型间的值复制 /// <summary> /// 交换两个类型的属性(复制) /// </summary> /// <typeparam name="Tin"></typeparam> /// <typeparam name="Tout"></typeparam> public static class ExpressionCopy<Tin, Tout> {

java File类 打印目录树状结构(递归)

import java.io.File; /** * 递归遍历 * */ public class FieTree { public static void main(String[] args) { File f = new File("D:/java笔记"); printFile(f,0); } static void printFile(File file,int level){ for(int i=0;i<level;i++){ System.out.print(&quo

《项目架构那点儿事》——工具类,你喜欢你就拿去

[前言]众所周知,各式各样的Util类为我们提供了便利,也同时减少了我们对底层硬编码的时间,包括对字符串的操作,文件操作,反射的操作,泛型的操作,以及熟知 的分页类,Json解析类.日期工具类等,这里把我开发的项目中用到过的工具类分享出来,都是经过多个项目的开发积累而锤炼出来的,提供给大家交流和学 习. [目录]            1.文件操作类 FileUtil            2.反射工具类 ReflectionUtil            3.泛型工具类 GenericsUti

java 13-2 Arrays工具类

1.Arrays:针对数组进行操作的工具类.比如说排序和查找. 1:public static String toString(int[] a) 把数组转成字符串  2:public static void sort(int[] a) 对数组进行排序  3:public static int binarySearch(int[] a,int key) 二分查找 1 import java.util.Arrays; //通过API查找,并不属于long包,所以需要导包 2 public class