我們都知道,在機房重構中,剛開始看的三層視頻,返回值類型是實體,後來用了SqlHelper,返回值類型就變成了Datatable,那這些,和今天要說的泛型有什麼關系呢?或者說,我們為什麼要大費周折的去用泛型呢?
原理
實體類即數據庫的映射,因此實體類中的屬性和數據庫表中的字段是相對應的。把DataTable中的每一行記錄視為一個實體類,把其中的字段讀取出來,存放到實體類的屬性中,再把所有的實體類存在泛型集合中。因此,DataTable中有多少個記錄,泛型集合中就有多少個實體類,每個實體類的屬性和DataTable的字段是相對應的。
1、編寫B層的人員無需手動填寫需要的字段,直接按一下點,全都提示出來了,想用哪個用哪個,不會出現寫錯的情況。
2、不必了解數據庫結構。
3、符合面向對象思想。
4、實體類的屬性是強類型,每個字段的類型都是已知的。
1、實體類的屬性名必須和數據庫表中的字段名一模一樣。
2、想用這種方法把DataTable轉換成實體類,必須有已知的實體類和DataTable中的數據相對應,也就是說必須明確你要轉換成的實體類類型,否則沒辦法指定泛型集合的類型,也就沒辦法調用。
3、各個表的字段盡量區別開來,不要相同。比如A表有個name字段,B表也有一個name字段,就不合理了。
說了這麼多,那麼,到底如何來實現Datatable轉泛型呢?我們先看代碼。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Collections; using System.Reflection; namespace SqlDAL { public class ConvertHelper { public ListconvertToList (DataTable dt) where T : new() { // 定義集合 List ts = new List (); // 獲得此模型的類型 Type type = typeof(T); //定義一個臨時變量 string tempName = string.Empty; //遍歷DataTable中所有的數據行 foreach (DataRow dr in dt.Rows) { T t = new T(); // 獲得此模型的公共屬性 PropertyInfo[] propertys = t.GetType().GetProperties(); //遍歷該對象的所有屬性 foreach (PropertyInfo pi in propertys) { tempName = pi.Name;//將屬性名稱賦值給臨時變量 //檢查DataTable是否包含此列(列名==對象的屬性名) if (dt.Columns.Contains(tempName)) { // 判斷此屬性是否有Setter if (!pi.CanWrite) continue;//該屬性不可寫,直接跳出 //取值 object value = dr[tempName]; //如果非空,則賦給對象的屬性 if (value != DBNull.Value) pi.SetValue(t, value, null); } } //對象添加到泛型集合中 ts.Add(t); } return ts; } } }
DataTable table =SqlDAL.SQLHelper.GetDataTable(sql, CommandType.Text, sqlParams);//調用SqlHelper中的有返回值的方法 if (table.Rows.Count > 0) { ConvertHelper ctl = new ConvertHelper(); Listlist = new List (); list = ctl.convertToList (table); return list; } else { return null; }
txtRate.Text = list[0].Rate.ToString(); txtTmpRate.Text = list[0].TmpRate.ToString(); txtPrepare.Text = list[0].PrepareTime.ToString(); txtLimit.Text = list[0].LimitCash.ToString(); lblModUser.Text = list[0].Head.ToString();
想要做出來一個功能,有很多方法,我們的任務不僅僅是掌握這些方法,更重要的是分析這些方法,區別這些方法,找到它們各自的優缺點,這樣才能更好的使用這些方法。