糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > C#利用反射将Datatable转化为指定实体类ListT

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

时间:2021-01-07 03:03:39

相关推荐

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

背景介绍

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

其二、利用传统的 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》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。