相信大家在做項目中,經常會根據不同的表new各種不同的Model,當需要對Model進行實例化的時候,先將數據從資料庫取出,將該數據中的每個值都賦值給一個model,假如你有10個Model,每次都會從不同的表中獲取數據,需要處理的數據完全不同,那麼就要寫10個方法,對著10個Model進行賦值。編...
相信大家在做項目中,經常會根據不同的表new各種不同的Model,當需要對Model進行實例化的時候,先將數據從資料庫取出,將該數據中的每個值都賦值給一個model,假如你有10個Model,每次都會從不同的表中獲取數據,需要處理的數據完全不同,那麼就要寫10個方法,對著10個Model進行賦值。編碼效率又低又low。為提高代碼通用性,故寫了個通用方法,實現datatable賦值model。
表結構(只是為了做演示,故沒有對錶中列屬性進行相關設置,預設都允許為null):
CREATE TABLE [AddressInfo](
[Name] [NVARCHAR](20) NULL,
[Sex] [NVARCHAR](2) NULL,
[Address] [NVARCHAR](50) NULL,
[Age] [INT] NULL,
[Birthday] [DATE] NULL
)
Model類:
1 public class AddressInfoModel
2 {
3
4 /// <summary>
5 /// 姓名
6 /// </summary>
7 public string Name { get; set; }
8 /// <summary>
9 /// 性別
10 /// </summary>
11 public string Sex { get; set; }
12 /// <summary>
13 /// 地址
14 /// </summary>
15 public string Address { get; set; }
16 /// <summary>
17 /// 年齡
18 /// </summary>
19 public int? Age { get; set; }
20 /// <summary>
21 /// 生日
22 /// </summary>
23 public DateTime? Birthday { get; set; }
24
25 }
通常我們得到Model實體是這樣進行的:
1 /// <summary>
2 /// 得到一個對象實體
3 /// </summary>
4 public AddressInfo DataRowToModel(DataRow row)
5 {
6 Maticsoft.Model.addressinfo model=new Maticsoft.Model.addressinfo();
7 if (row != null)
8 {
9 if(row["id"]!=null && row["id"].ToString()!="")
10 {
11 model.id=int.Parse(row["id"].ToString());
12 }
13 if(row["name"]!=null)
14 {
15 model.name=row["name"].ToString();
16 }
17 if(row["Sex"]!=null)
18 {
19 model.Sex=row["Sex"].ToString();
20 }
21 if(row["Address"]!=null)
22 {
23 model.Address=row["Address"].ToString();
24 }
25 if(row["Age"]!=null && row["Age"].ToString()!="")
26 {
27 model.Age=int.Parse(row["Age"].ToString());
28 }
29 if(row["Birthday"]!=null && row["Birthday"].ToString()!="")
30 {
31 model.Birthday=DateTime.Parse(row["Birthday"].ToString());
32 }
33 }
34 return model;
35 }
36
相信這是大家常用的方法,該方法的好處是簡單,容易理解,但是這樣寫會存在一個弊端,那就是方法通用性極差,甚至根本就沒有通用性,而且日後也不易維護。
試想一下:
(1)如果我們有100個Model需要賦值,按照這樣來做,我們豈不是需要寫100個這樣的方法來進行Model的賦值?
(2)一旦其中Model屬性發生改變,那麼對應的方法也必鬚髮生相應的修改,如果客戶不斷提出改變要對Model屬性進行修改,那工作量豈不是很大?
天哪!這工作量簡直不敢想象。
通過對上面的思考,我們不難發現,不管有多少個Model其實在對其進行賦值時,所進行的邏輯處理都是有規律的重覆性的工作,即將DataRow中的列賦值給對應Model屬性。
經過一番努力終於通用方法第一個版本出爐(廢話不多說直接上乾貨!)
(1)DataRow賦值Model通用方法之版本一:(該方法淘汰,僅為大家提供思路)
1 /// <summary>
2 /// 將DataRow中數據賦值給model中的同名屬性
3 /// </summary>
4 /// <typeparam name="T">泛型:model的類型</typeparam>
5 /// <param name="objmodel">model的實例</param>
6 /// <param name="dtRow">DataRow</param>
7 public T TableToModel<T>(T objmodel, DataRow dtRow)
8 {
9 //獲取model的類型
10 Type modelType = typeof(T);
11 //獲取model中的屬性
12 PropertyInfo[] modelpropertys = modelType.GetProperties();
13 //遍歷DataTable的每一列
14 //遍歷model的每一個屬性
15 foreach (PropertyInfo pi in modelpropertys)
16 {
17 //獲取屬性名稱
18 String name = pi.Name;
19 //將DataRow中數據賦值給model中的同名屬性(不區分屬性名稱大小寫name和Name效果一樣)
20 if (dtRow.Table.Columns.Contains(name))
21 {
22 object value = dtRow[name].ToString();
23 pi.SetValue(objmodel, value, null);
24 }
25 }
26 }
通過測試發現,該方法對於Model屬性都是string類型的沒有問題,該Model中Age為Int類型,Birthday為DateTime類型,會發生類型不能匹配的錯誤,故通用性極差。在此基礎上出現了通用版本二
(2)DataRow賦值Model通用方法之版本二:(該方法淘汰,僅為大家提供思路)
將22行代碼
22 object value = dtRow[name].ToString();
修改為
object value = Convert.ChangeType(dtRow[name], modelType.GetProperty(name).PropertyType);
解決DataRow類型與Model類型不匹配問題
此時,該方法已經很好的通用性,著實高興了一下,但是當測試中,資料庫中自讀允許為null的情況下,該方法便不能適應複雜多變的Model賦值。例如該類中年齡和出生年月欄位是允許為空的
即 int? Age 和DateTime? Birthday會報錯,不能將null值賦值給指定的數據類型,因為進一步改進該方法,最終版本如下:
(3)DataRow賦值Model通用方法之最終版:
1 /// <summary>
2 /// 將DataRow賦值給model中同名屬性
3 /// </summary>
4 /// <typeparam name="T">泛型:model的類型</typeparam>
5 /// <param name="objmodel">model實例</param>
6 /// <param name="dtRow">DataTable行數據</param>
7 public T TableRowToModel<T>(T objmodel, DataRow dtRow)
8 {
9 //獲取model的類型
10 Type modelType = typeof(T);
11 //獲取model中的屬性
12 PropertyInfo[] modelpropertys = modelType.GetProperties();
13 //遍歷model每一個屬性並賦值DataRow對應的列
14 foreach (PropertyInfo pi in modelpropertys)
15 {
16 //獲取屬性名稱
17 String name = pi.Name;
18 if (dtRow.Table.Columns.Contains(name))
19 {
20 //非泛型
21 if (!pi.PropertyType.IsGenericType)
22 {
23 pi.SetValue(objmodel, string.IsNullOrEmpty(dtRow[name].ToString()) ? null : Convert.ChangeType(dtRow[name], pi.PropertyType), null);
24 }
25 //泛型Nullable<>
26 else
27 {
28 Type genericTypeDefinition = pi.PropertyType.GetGenericTypeDefinition();
29 //model屬性是可為null類型,進行賦null值
30 if (genericTypeDefinition == typeof(Nullable<>))
31 {
32 //返回指定可以為 null 的類型的基礎類型參數
33 pi.SetValue(objmodel, string.IsNullOrEmpty(dtRow[name].ToString()) ? null : Convert.ChangeType(dtRow[name], Nullable.GetUnderlyingType(pi.PropertyType)), null);
34 }
35 }
36 }
37 }
38 return objmodel;
39 }
最終實現DataRow數據賦值給Model
通過該方法便可簡單實現將DataTable賦值給List<Model>!!(此處便不再給大家演示)