標籤:
剛開始在機房重構中用的最多的是Datatable,之前沒有開始的時候就聽大家一直在說泛型,很好奇這個東西,也很想知道明明用Datatable就可以,為什麼非要轉成泛型?它到底有什麼好處呢?於是,便開始了研究……
Datatable是一個臨時儲存資料的網格,是一個虛擬表。我們在使用Datatable時,通過D層直接將資料庫中的資料選出來,返回到B層和U層,在返回的時候我們要是想顯示到表單,就需要將U層的文字框與這個表中的欄位一一對應。如果不小心就會寫錯,然後資料顯示就不對。這樣對資料庫的耦合性太大,不能保證資料庫的安全性。
例如我們的學生查詢餘額這個功能,如果使用Datatable,則為:
<span style="font-size:18px;">If card.Rows.Count Then txtClass.Text = card.Rows(0)(5).ToString() txtName.Text = card.Rows(0)(3).ToString() txtDepartment.Text = card.Rows(0)(8).ToString() txtGrass.Text = card.Rows(0)(4).ToString() txtSex.Text = card.Rows(0)(2).ToString() txtState.Text = card.Rows(0)(7).ToString() txtCash.Text = card.Rows(0)(6).ToString() txtStuNo.Text = card.Rows(0)(1).ToString() End If </span>
這樣做功能可以實現,但是卻存在一些不完美之處:
1、 必須瞭解資料庫的結構,破壞了資料庫的安全性。
2、 在代碼編寫過程容易寫錯,因為我們要用虛擬表中各個欄位的編號來進行對應,而且這種錯誤編譯器不會進行提示。
3、 在程式中進行資料傳遞的是Datatable,不再是實體,違背了三層的思想。
Datatable為弱類型,無法直觀的看出欄位的資料類型。當資料少的時候我們可以一一進行對應,但是如果資料很多的時候Datatable就會有很多想不到的麻煩。所以我們將Datatable轉換為泛型。
泛型是具有預留位置(型別參數)的類、結構、介面和方法,這些預留位置是類、結構、介面和方法所儲存或使用的一個或多個類型的預留位置。泛型集合類可以將型別參數用作它所儲存的隊形的類型的預留位置;型別參數作為其欄位的類型及其方法的參數類型出現。
那麼泛型有什麼好處呢?
1、 減少輸入,傳輸時只需要傳一個執行個體T就可以擷取它的任何屬性,便利方便,取到的都是單個的對象。
2、 正確的構建泛型類可以真正的減少代碼中的安全性問題。
3、 使用泛型類還可以提高效能。
Datatable轉換為泛型的核心思想圖:
實體就是資料庫中表的映射,因為實體中的每個屬性都和資料庫表中的欄位相對應。Datatable中的每一行記錄視為一個實體類,把其中的欄位讀取出來,存放到實體類的屬性中,再把所有的實體類都存放到泛型集合中,因此,Datatable中有多少條記錄,泛型集合中就有多少個實體。
那具體Datatable是怎麼轉化成泛型的呢?
<span style="font-size:18px;">Imports System.Collections.Generic ' 添加泛型集合的命名空間Imports System.Reflection '添加反射'/*****************************************'類 名 稱:ModelHelper'命名空間:JFDAL'建立時間:2015/7/13 11:31:37'作 者:邢玉'小 組:'修改時間:'修 改 人:'版 本 號:v1.0.0'******************************************'實現datatable轉換成泛型的功能Public Class ModelHelper Public Shared Function convertTolist(Of T As {New})(ByVal dt As DataTable) As IList(Of T) '獲得T的類型 Dim type As Type = GetType(T) Dim ts As New List(Of T) '定義一個臨時變數 Dim strTemp As String = String.Empty '遍曆表中所有行數 For Each dr As DataRow In dt.Rows '定義類型變數Act擷取動態建立對象T的類型 Dim act As T = If((Nothing Is Nothing), Activator.CreateInstance(Of T)(), Nothing) '引用反射表示可獲得對象的所有屬性群組成的集合 Dim propertys As PropertyInfo() = act.[GetType]().GetProperties() '定義array變數,接收propertys中含有的屬性,並提供對屬性propertys中繼資料訪問 Dim array As PropertyInfo() = propertys Dim intCount As Integer = 0 '遍曆所有對象屬性 While intCount < array.Length 'length 表示所有維數中元素的總和 'pr表示元素中含有的屬性,並提供對資料訪問 Dim pr As PropertyInfo = array(intCount) strTemp = pr.Name '列名=對象的屬性名稱 If dt.Columns.Contains(strTemp) Then '判斷此屬性是否設定函數 If pr.CanWrite Then '該屬性是否可寫 Dim value As Object = dr(strTemp) '如果非空,則賦值給對象的屬性 If value IsNot DBNull.Value Then '設這對象的屬性值 pr.SetValue(act, value, Nothing) End If End If End If intCount += 1 Continue While End While '添加對象到泛型集合中 ts.Add(act) Next Return ts End FunctionEnd Class</span>
然後在D層返回Datatable之後加一句調用這個方法的代碼就可以了。
<span style="font-size:18px;"> table = SqlHelper.ExecSelect(sql, CommandType.Text, sqlparam) list = JFDAL.ModelHelper.convertTolist(Of JFEntity.CardEntity)(table)</span>
總結:剛開始使用Datatable時也是可以滿足我們的,但是到了後面不能滿足我們了,我們就會進行新的探索,然後瞭解並使用泛型。這就是我們不將就的精神!
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
機房收費系統重構——Datatable轉泛型