DataTable數據賦值給Model通用方法

来源:http://www.cnblogs.com/xinlj/archive/2016/01/08/5113396.html
-Advertisement-
Play Games

相信大家在做項目中,經常會根據不同的表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>!!(此處便不再給大家演示)



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 來源:http://zxlovenet.cnblogs.com聲明:本文原創發表於博客園,作者為初行本文歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則視為侵權。從安裝到配置首先到官網http://www.nunit.org/下載如下圖的資料,安裝NUnit-2.6....
  • 主要介紹一下C#的delegate的用法以及如何實現類似javascript的each方法,並簡要說明delegate,Func, Action和 Predicate的區別
  • 前言最近在幫一家知名外企開發Universal Windows Platform的相關應用,開發過程中不由感慨:項目分為兩種,一種叫做前人栽樹後人乘涼,一種叫做前人挖坑後人遭殃。不多說了,多說又要變成月經貼了。講講MEF。MEF全稱Managed Extensibility Framework。我們...
  • 所謂條件表達式,就是分支語句,去掉分支語句咯1、分解條件表達式修改點:你有一個複雜的條件語句(就是if else語句)做法:將條件表達式的三個部分分別提煉出獨立函數即 if (A部分) { B部分; } ...
  • 說非同步前,首先講講這些概念,非同步/同步、多線程。 非同步:是指呼叫另一操作後,不等待其結果,繼續執行之後的操作,若之後沒有其他操作,當前線程將進入睡眠狀態,而CPU時間將有機會切至其他線程。在非同步操作完成後通過回調函數的方式獲取通知與結果。非同步的實現方式有多種,如多線程與完成埠。多線程將非同步操作放...
  • 在WPF中的實現和WinForm中的實現99%相似,將要實現接受拖拽釋放的控制項添加DragEnter事件和Drop事件,本例中控制項Grid grid作為接受控制項,添加事件操作如下:private void grid_Drop(object sender, DragEventArgs e){ stri...
  • 最近項目需要,要用到一個圖片查看器,類似於windows自帶的圖片查看器那樣,滑鼠滾動可以縮放,可以拖拽圖片,於是就寫了這個簡單的圖片查看器。前臺代碼: ...
  • A 窗體跳轉到B窗體代碼 A aa = new A(); aa.ShowDialog(this);//此處記得加this 當B窗體關閉須調用A 窗體時,可在A窗體添加共用方法 如: public void AA(){ //回到A時所需要實現的內容... } B 窗體 A aa; aa = (A)th...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...