1. 程式人生 > >vb.net & 泛型集合-解決Datatable強耦合

vb.net & 泛型集合-解決Datatable強耦合

     做基本資料設定窗體,本以為實現這個小小的窗體應該是最簡單的吧!不就是單擊修改按鈕,進行修改;然後單擊更新按鈕來對資料基本設定進行更新嗎?可是當一出手就遇到了問題,資料表中的資料該怎麼顯示在文字框中呢?這真的一下子難住了自己!不過遇到問題總會有解決的辦法。

     既然是讓實體一個一個返回到文字框中來,那麼直接呼叫實體層應該就可以吧!這樣不就可以完美的實現了嗎?可是這樣最大的缺點則是:以後遇到的控制元件與資料呼叫的窗體比比即是,這樣不就又重蹈覆轍實現了程式碼的重複嗎?很嚴重的違背了為了把重複的部分提取出來,方便以後的呼叫,所以用到了泛型集合。

     那麼首先分析一下什麼情況下使用泛型集合呢?在基本資料設定中,我們想要實現的功能就是將資料表中的資訊轉換成為一個一個的實體,然後新增到文字框中,所以我們就可以將資料表中的一個一個的實體作為引數傳遞給泛型型別,進而得到自己想要的。

     由於List是ArrayList的泛型等效類,屬於動態陣列,正好可以滿足自己的需求。我們可以講型別看做一個模板,這樣模板中的變體部分就可以被傳來的 類名稱所代替,從而得到一個新的定義。

在此之前對於實體層的建立是必不可少的,因為建立集合的基礎是要有類,然後才能將物件放入集合中。

建立的EntityModule:

'********************************
'說明:泛型集合,完成datatable型別轉化為實體類
'作者:霍亞靜
'小組:XX
'建立日期:2014-07-20 22:28:21
'版本號:V1.00
'********************************
Imports System.Collections.Generic    '增加泛型的名稱空間,用來管理泛型集合
Imports System.Reflection    '加入反射,為了引用 PropertyInfo
Public Class EntityModule
    '將datatable轉化為泛型集合
    Public Shared Function converToList(Of T As {New})(ByVal dt As DataTable) As IList(Of T)

        Dim myList As New List(Of T)    '定義最終返回的集合
        Dim myType As Type = GetType(T)   '得到實體類的型別名

        Dim dr As DataRow   '定義行集

        Dim TmpName As String = String.Empty    '定義一個臨時變數

        '遍歷datatable的所有資料行
        For Each dr In dt.Rows
            Dim myT As New T   '定義一個實體類的物件
            Dim propertys() As PropertyInfo = myT.GetType().GetProperties()   '定義屬性集合
            Dim pr As PropertyInfo
            '遍歷該物件的所有屬性
            For Each pr In propertys
                TmpName = pr.Name    '將屬性名稱賦值給全域性變數

                '檢查datatable是否包含此列,(列名==物件的屬性名)
                If (dt.Columns.Contains(TmpName)) Then    '將此屬性與datatable李的列名比較,檢視datatable是否包含此屬性
                    '判斷此屬性是否有setter(類)
                    If (pr.CanWrite = False) Then    '判斷此屬性是否可寫,如果不可寫,跳出此迴圈
                        Continue For
                    End If
                    Dim value As Object = dr(TmpName)    '定義一個物件型的列來儲存列的值

                    If (value.ToString <> DBNull.Value.ToString()) Then      '判斷是否為空,如果非空,則賦給物件的屬性
                        pr.SetValue(myT, value, Nothing)     '在執行期間通過反射,動態的訪問一個動態的屬性
                    End If
                End If
            Next
            myList.Add(myT)    '新增到集合
        Next
        Return myList   '返回實體集合
    End Function
End Class
這樣D層就可以直接呼叫將T_datatable中表集轉化成泛型集合
 Public Function ReadBasic() As IList(Of Entity.BasicDataEntity) Implements IDAL.IBasicDataDAL.ReadBasic    '應該使用泛型集合型別


        ''Dim sqlparams As SqlParameter() = {}  '宣告並例項化引數陣列

        '呼叫無引數查詢()
        'Return clsSqlhelper.Query(strSQL, CommandType.Text)    '呼叫sqlHelper
        'Return table             '返回查詢結果
        'Dim mySqlhelper As Ne'w Sqlhelper.sqlhelper   '定義查詢助手類,上文已經定義
        Dim dt As New DataTable   '定義查詢到的表集
        Dim myList As List(Of Entity.BasicDataEntity)    '儲存轉換後的泛型集合
        Dim strSQL As String = "select * from T_BasicData "  '宣告並例項化需要執行的SQL語句

        dt = clsSqlhelper.Query(strSQL, CommandType.Text)   '執行查詢
        '將dt轉換為泛型集合
        myList = EntityModel.converToList(Of BasicDataEntity)(dt)
        Return myList    '返回一個實體

    End Function
其實整個過程也只是呼叫了一下泛型集合,改變了一下其型別,和datatable的使用過程還是一樣的。

Public Function ReadBasic() As IList(Of Entity.BasicDataEntity)
        '宣告並例項化變數InBasic為:呼叫Factory所返回來的IBasicDataDAL
        Dim inBasic As IBasicDataDAL = factory.BasicDataDAL()     '事先要宣告factory的型別,已宣告並例項化factory為DataAccess類
        '宣告並例項化變數ReadB
        Dim ReadB As IList(Of Entity.BasicDataEntity)
        ReadB = inBasic.ReadBasic()

        Return ReadB     '返回ReadB這個泛型陣列

    End Function

這樣在U層就可以直接呼叫其陣列,然後顯示在文字框中了

 Dim ReadB As IList(Of BasicDataEntity)      '定義泛型集合
        Dim RBasic As New BasicDataBLL           '定義一個b層介面

        ReadB = RBasic.ReadBasic()

        txtRate.Text = ReadB(0).Rate
        txtTmpRate.Text = ReadB(0).TmpRate
        txtLimitCash.Text = ReadB(0).limitCash
        txtLeastTime.Text = ReadB(0).leastTime
        txtPrepareTime.Text = ReadB(0).prepareTime
        txtUnitTime.Text = ReadB(0).unitTime

顯示效果圖:


注:

     其實做完之後,突然又覺得T_datatable中只是存在一條資料,如果僅僅只是來查詢一條資料的話,或許直接呼叫實體層會更簡單一點,又比如登陸窗體,當然也可以直接呼叫泛型集合,但是對此也只是想查詢對應的使用者名稱和密碼,僅此而已!如果單單的是一個窗體的話,真的是感覺有點大材小用啊!就好像一個大大的水缸,你偏偏在裡邊放一升的水,那是不是多此一舉呢?還不如直接拿一個小小的水杯盛放,來得更直接一些。

     在此使用泛型集合,一是想熟悉一下,再者,整個系統需要用到泛型集合的地方有很多,這裡也只是呼叫了一下公共的部分,減少了重複的程式碼,又何樂而不為呢?