背景介绍

在软件开发中肯定免不了和数据库打交道,我们对数据的增删改查最终会转化为SQL在数据库中执行。从SQLServer中查出数据一般有两种方式:一是ADO.NET直接写SQL语句从数据中查出数据,另一种是利用ORM框架得到数据。ADO.NET作为传统的数据库对接方式现在貌似已经不怎么流行了。让程序员直接写SQL实现增删改查功能存在一定和风险并且在程序中写SQL非常不利于程序的扩展和维护,也不利于数据库的维护和更换,极大的增加了程序的不稳定性。

其二、利用传统的ADO.NET Datatable的数据操作语法十分繁琐,并且装箱拆箱的效率十分低下,因此,对数据的操作应该使用实体类。那么问题来了,对于那些由于各种原因还没有利用起ORM框架,但是想利用实体类进行数据操作的程序,我们只需要将Datatable中的数据转化为实体类,便可实现。废话不多说,代码如下所示:

public static class DatatableExtension
{/// <summary>/// 将Datatable转化为指定实体类/// </summary>/// <typeparam name="T">实体类对象类型</typeparam>/// <param name="_sourceTable">源DataTable</param>/// <returns>返回转化后的DataTable</returns>public static List<T> ToList<T>(this DataTable _sourceTable) where T : new(){var resultLists = new List<T>();var pi = typeof(T).GetProperties(BindingFlags.Public|BindingFlags.Instance|BindingFlags.DeclaredOnly).ToList();if (_sourceTable == null || pi == null || pi.Count == 0){//DataTable为null或实体类无属性则返回空的实体类}else{var wildColumnsLists = new List<string>();//用于存放无法找到对应实体类属性的列,无后续操作var piFlagLists = new List<Tuple<PropertyInfo, bool>>();//用于存放找到对应实体类属性的列,二元组T1是列的数据类型,T2是类型是否和实体类是否相等foreach (DataColumn col in _sourceTable.Columns){if (pi.Exists(p => p.Name.Equals(col.ColumnName))){var prop = pi.FirstOrDefault(q => q.Name.Equals(col.ColumnName));piFlagLists.Add(Tuple.Create(prop, prop.PropertyType.Equals(col.DataType)));}else{wildColumnsLists.Add(col.ColumnName);}}foreach (DataRow dr in _sourceTable.Rows){T targetEntity = new T();foreach (var piFlag in piFlagLists){if (piFlag.Item1.SetMethod != null && !piFlag.Item1.PropertyType.IsGenericType && !dr.IsNull(piFlag.Item1.Name)){//赋值操作,如类型不相同则以实体类为准并赋值piFlag.Item1.SetValue(targetEntity, piFlag.Item2 ? dr[piFlag.Item1.Name] : Convert.ChangeType(dr[piFlag.Item1.Name], piFlag.Item1.PropertyType));}else{//无法赋值的情况:1、set访问器不存在2、此属性为泛型3、Datatable中招不到需要转换的列名}}resultLists.Add(targetEntity);}}return resultLists;}/// <summary>/// 将筛选后的Datatable转化为指定实体类/// </summary>/// <typeparam name="T"></typeparam>/// <param name="_sourceTable">源DataTable</param>/// <param name="_predicate">执行筛选的委托</param>/// <returns>返回执行筛选转化后的DatatTable</returns>public static List<T> ToList<T>(this DataTable _sourceTable, Func<DataRow, bool> _predicate) where T : new(){var whereDT = _sourceTable.Where(_predicate);return whereDT.ToList<T>();}/// <summary>/// 在Datatable中使用Where方法进行筛选/// </summary>/// <param name="_sourceTable">源DataTable</param>/// <param name="_whereFunc">执行筛选的委托</param>/// <returns>筛选后的DataTable</returns>public static DataTable Where(this DataTable _sourceTable, Func<DataRow, bool> _predicate){if (_sourceTable == null){throw new ArgumentNullException(nameof(_sourceTable));}else{if (_predicate == null){return _sourceTable;}else{var rowLists = _sourceTable.AsEnumerable().Where(_predicate);var resultDataTable = rowLists.Count() == 0 ? _sourceTable.Clone() : rowLists.CopyToDataTable();return resultDataTable;}}}/// <summary>/// 在Datatable中调用Select方法进行选取/// </summary>/// <typeparam name="T">选取结果类型</typeparam>/// <param name="_sourceTable">源Datatable</param>/// <param name="_selector">执行委托</param>/// <returns></returns>public static List<T> Select<T>(this DataTable _sourceTable, Func<DataRow, T> _selector){if (_sourceTable == null){throw new ArgumentNullException(nameof(_sourceTable));}else{if (_selector == null){throw new ArgumentNullException(nameof(_sourceTable));}else{var resultLsit = _sourceTable.AsEnumerable().Select(_selector).ToList();return resultLsit;}}}/// <summary>/// 直接在当前DataTable对象上调用Any方法进行判断/// </summary>/// <param name="_dt">当前DataTable变量</param>/// <param name="_anyFunc">执行Any方法的委托</param>/// <returns>结果,true:代表有元素满足条件,false :代表没有元素满足条件</returns>public static bool Any(this DataTable _dt, Func<DataRow, bool> _predicate){if (null != _dt && null != _predicate){var reuslt = _dt.AsEnumerable().Any(_predicate);return reuslt;}else{throw new ArgumentNullException(string.Format("{0}|{1}", null == _dt ? nameof(_dt) : string.Empty, null == _predicate ? nameof(_predicate) : string.Empty));}}/// <summary>/// DataTable的ForEach扩展方法/// </summary>/// <param name="_dt">当前dt</param>/// <param name="_action">要执行的委托</param>public static void ForEach(this DataTable _dt, Action<DataRow> _action){if (null == _dt){throw new ArgumentNullException(nameof(_dt));}if (null == _action){throw new ArgumentNullException(nameof(_action));}_dt.AsEnumerable().ToList().ForEach(row => _action(row));}/// <summary>/// 获取当前DataTable对象的满足委托条件的第一个datarow/// </summary>/// <param name="_dt"></param>/// <param name="_predicate"></param>/// <returns></returns>public static DataRow FirstOrDefault(this DataTable _dt, Func<DataRow, bool> _predicate){if (null == _predicate){throw new ArgumentNullException(nameof(_predicate));}return _dt.AsEnumerable().FirstOrDefault(_predicate);}/// <summary>/// 获取当前DataTable对象的满足委托条件最后一个datarow/// </summary>/// <param name="_dt"></param>/// <param name="_predicate"></param>/// <returns></returns>public static DataRow LastOrDefault(this DataTable _dt, Func<DataRow, bool> _predicate){if (null == _predicate){throw new ArgumentNullException(nameof(_predicate));}return _dt.AsEnumerable().LastOrDefault(_predicate);}
}

在DatatableExtension类中,前两个两个扩展方法;一个是方法直接将Datatable转化为指定的实体类,第二个方法支持将Datatable进行委托筛选后转化为指定实体类,操作代码如下图所示:

string sql = string.Format(@"SELECT  A.UserID ,A.UserName ,A.UserPwd ,FROM  dbo.TabUsers AS A ");
DataSet ds = dbhelp.JustGetData(sql);//查询出sql语句对应的数据
List<TabUser> UserLists = ds.Tables[0].ToList<TabUser>();//将DataTable转化为TabUser实体类
List<TabUser> easyUserLists = ds.Tables[0].ToList<TabUser>(p => p["UserName"].ToString().Contains("车间"));//筛选出UserName包含“车间”字段的数据public class TabUser:EntityBase
{public string UserName { get; set; }public string UserPwd { get; set; }public long UserID { get; set; }
}

C#利用反射将Datatable转化为指定实体类ListT相关推荐

  1. C# 将DataTable数据源转换成实体类

    1 using System; 2 using System.Collections.Generic; 3 using System.Data; 4 using System.Reflection; ...

  2. C#利用反射将实体类ListT转化为Datatable

    背景介绍 C#中实体类的操作十分简便,一般情况下不需要涉及ADO.NET,如果需要将实体类转化为Datatable,这个时候就需要手动写一个方法了,代码如下图所示: public static cla ...

  3. C#利用反射实现实体类ListT索引器

    相关背景: 在项目开发中,我们经常会自定义一些实体类,在某些需要动态赋值的功能中,我们无法知道到下一个需要赋值的字段名称是什么,只知道会从其他返回需要赋值的字段名称和值,这时候就需要实现索引器了,就像 ...

  4. c# DataTable与不同结构实体类转换的方法实例

    1.实体类样例Person.cs /// <summary> /// 具体的实体类,和数据表中不同 /// </summary> public class Person {[D ...

  5. 一个简单的反射拷贝一份新的实体类

    有时候我们需要复制一个实体类,而又不希望两个使用同一个内存地址,我用了很简单的反射来实现这种功能:) /**//// <summary>         /// 设置实体对象的修改属性   ...

  6. JSON字符串转为指定实体类对象

    创建JsonStringToClass对象即可 package utils;import net.sf.json.JSONArray; import net.sf.json.JSONObject;im ...

  7. [转]一个简单的反射拷贝一份新的实体类

    [IT168技术文档]   有时候我们需要复制一个实体类,而又不希望两个使用同一个内存地址,我用了很简单的反射来实现这种功能: /** <summary> /// 设置实体对象的修改属性 ...

  8. 使用反射将req.getParameterMap()赋值给实体类

    这是一个将Map<String, String[]> 类型的map集合赋值给一个实体类. 这个map集合是以   map={ key1 = {value1 , value2} ,key2= ...

  9. (转)DataTable与结构不同实体类之间的转换

    原文地址:http://www.cnblogs.com/kinger906/p/3428855.html 在实际开发过程中,或者是第三方公司提供的数据表结构,与我们系统中的实体类字段不对应,遇到这样我 ...

最新文章

  1. Tesseract 3 语言数据的训练方法
  2. goland 设置project gopath
  3. 数据访问模式二:数据集和数据适配器(传统的数据访问模式)
  4. 盘点计算机世界那些经典谣言
  5. cacti pdo_mysql_搭建配置cacti,采集信息监控
  6. mvvm怎么让光标制定属性的文本框_Word怎么快速制作斜线表头?10秒搞定,表格颜值直线上升...
  7. 一个复平面上的不等式
  8. vs2010变的特别卡解决办法
  9. Windows 7精简版(2019)
  10. 短视频新媒体运营策划推广工作计划表模板
  11. 魔兽争霸3运行速度慢的一些优化办法。
  12. python 图表控件_10款好用的.NET图表控件推荐
  13. oracle19c报价_Oracle 19c下载
  14. 卡西欧科学计算机使用方法,科学计算器的使用方法
  15. Excel 技巧百例:数据透视表的简单使用-行列转换
  16. MarkDown转Html在线转换(支持代码高亮,可复制到微信公众号、今日头条)
  17. CVPR 2022 Oral | 人大高瓴AI学院提出:面向动态视音场景的问答学习机制
  18. 计算机论文封皮,毕业论文封面及格式规定
  19. java 变位词,java程序 问题: 判断两个单词是否为变位词。
  20. Ymodem协议介绍

热门文章

  1. Node.js meitulu图片批量下载爬虫1.051
  2. J2EE基础之Web服务简介
  3. 同事反馈环:如何实现持续改进的文化
  4. ubuntu双系统导致进windows花屏
  5. easyUI layout 中使用tabs+iframe解决请求两次方法
  6. Crazy Drops 3
  7. Android app 应用签名
  8. android 按键上浮动画_android – 浮动动作按钮动画
  9. python输出日期语句_如何从Python的原始语句中提取时间-日期-时间段信息
  10. java set是重复_java算法题,set内出现重复元素