一、概述

在项目中经常会使用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 = ; 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 <= )
throw new ArgumentNullException("dataTable", "当前对象为null无法生成表达式树");
Func<DataRow, T> func = dataTable.Rows[].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 = ; 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的更多相关文章

  1. 05.表达式目录树Expression

    参考文章 https://www.cnblogs.com/xyh9039/p/12748983.html 1. 基本了解 1.1 Lambda表达式 演变过程 using System; namesp ...

  2. 【手撸一个ORM】第五步、Expression(表达式目录树)转换为Where子句

    说明 在SQL中,查询.修改比较常用到WHERE子句,在这里根据使用场景不同,定义了两个类,一个用于查询,一个用于修改(插入)操作.原因是: 查询操作支持一级导航属性查询,如student.Schoo ...

  3. 【手撸一个ORM】第四步、Expression(表达式目录树)扩展

    到这里,Orm的基架已经搭起来了,接下来就是激动人心的部分,表达式目录树转Sql语句,SqlDataReader转数据实体等等,但是在这之前,我们需要扩展下表达式目录树的方法,以方便后面的相关操作. ...

  4. 第十五节:Expression表达式目录树(与委托的区别、自行拼接、总结几类实例间的拷贝)

    一. 基本介绍 回忆: 最早接触到表达式目录树(Expression)可能要追溯到几年前使用EF早期的时候,发现where方法里的参数是Expression<Func<T,bool> ...

  5. 表达式目录树(Expression)

    一:什么是表达式树 Expression我们称为是表达式树,是一种数据结构体,用于存储需要计算,运算的一种结构,这种结构可以只是存储,而不进行运算.通常表达式目录树是配合Lambda一起来使用的,la ...

  6. MVC图片上传详解 IIS (安装SSL证书后) 实现 HTTP 自动跳转到 HTTPS C#中Enum用法小结 表达式目录树 “村长”教你测试用例 引用provinces.js的三级联动

    MVC图片上传详解   MVC图片上传--控制器方法 新建一个控制器命名为File,定义一个Img方法 [HttpPost]public ActionResult Img(HttpPostedFile ...

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

    dnSpy应该是目前使用最多的.net反编译工具.很多情况下反编译C#代码非常方便,特别是查找基类,子类.搜索一些class,方法.接口,非常方便.比ILspy好很多.而且dnspy是可以配置的. 如 ...

  8. c# 表达式目录树拷贝对象(根据对象类型动态生成表达式目录树)

    表达式目录树,在C#中用Expression标识,这里就不介绍表达式目录树是什么了,有兴趣可以自行百度搜索,网上资料还是很多的. 这里主要分享的是如何动态构建表达式目录树. 构建表达式目录树的代码挺简 ...

  9. Expression表达式目录树

    一.初识Expression 1.在上一篇我们讲到了委托(忘记了可以在看看,点赞在看养成习惯),今天要讲的Expression也和委托有一点点关系吧(没有直接关系,只是想要大家看看我其他的文章),Ex ...

随机推荐

  1. redis 配置及编写启动脚本

    #!/bin/sh # # Simple Redis init.d script conceived to work on Linux systems # as it does use of the ...

  2. 如何在Ubuntu编译ice

    摘要:所有操作都在root用户下执行 第一步:下载ice最新版本,以3.7版本为例 第二步:安装ICE依赖包里面的三方库 #apt-get install libmcpp-dev;apt-get in ...

  3. STP:生成树协议解决网络冗余问题

    STP(Spanning Tree Protocol)是生成树协议的英文缩写,可应用于计算机网络中树形拓扑结构建立,主要作用是防止网桥网络中的冗余链路形成环路工作.但某些特定因素会导致STP失败,要排 ...

  4. MySql学习笔记三

    MySql学习笔记三 4.DML(数据操作语言) 插入:insert 修改:update 删除:delete 4.1.插入语句 语法: insert into 表名 (列名1,列名2,...) val ...

  5. Linux上安装git

    Linux上安装git Git是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理. 而国外的GitHub和国内的Coding都是项目的托管平台.但是在使用Git工具的时候 ...

  6. UGUI在两个UI间坐标转换

    在UGUI中,在两个Canvas之间进行坐标转换,从CanvasA下的坐标转换到CanvasB下. 或者在同一个界面下,从不同的节点下,转成相同的坐标. 函数定义 public static bool ...

  7. 06webpack-- html-webpack-plugin的2个作用

    <!-- 15 html-webpack-plugin的2个作用 下载 cnpm i html-webpack-plugin -D 作用在==>内存中生成页面 在webpack中 导入在内 ...

  8. re 模块详解

    1.re 模块 regex 1.查找 :findall 意思"匹配所有,每一项都是列表的组成元素" 有返回值 import re ret=re.findall("\d+& ...

  9. webpack开发指南1

    怎么安装Webpack 安装node.js 首先需要安装Node.js,node自带了包管理工具npm. 安装webpack 使用npm install webpack -g,webpack全局安装到 ...

  10. 201871010114-李岩松《面向对象程序设计(java)》第十五周学习总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...