C#利用反射将Datatable转化为指定实体类ListT
生活随笔
收集整理的這篇文章主要介紹了
C#利用反射将Datatable转化为指定实体类ListT
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
背景介紹
? ? ? ? ? 在軟件開發中肯定免不了和數據庫打交道,我們對數據的增刪改查最終會轉化為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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 将C#中DateTime类型转化为Jav
- 下一篇: 蓝桥杯 算法训练(四)结点选择(树形动态