1. 程式人生 > >.NET重構(四):窗體繼承+模板方法,完美實現組合查詢

.NET重構(四):窗體繼承+模板方法,完美實現組合查詢

導讀:在機房重構中,有好些個查詢都是大同小異,最為顯著的就是組合查詢了。怎樣給自己省事兒,相同的東西能不能重複利用,就成了一個現實的問題。第一遍做機房的時候,使用的更多的是:複製+貼上。學習了設計模式後,可以用模板方法解決。這篇文章,就通過窗體繼承和模板方法,實現組合查詢。

觀點:組合查詢在機房中有3中情況,其實,組合查詢完全可以看到是一種查詢情況。

一、窗體繼承的使用

1,首先建立一個父窗體

2,新增一個新項

3,選擇繼承窗體

4,確定後,一個新的繼承窗體就好了。

二、模板方法的使用

備註:定義一個組合查詢的實體,方便傳參

1,首先在U層寫入基礎方法和傳參

<span style="font-size:18px;">Public Class FrmGroupQuery
    Public enGroupQuery As New Model.GroupQueryM  '定義一個實體引數
    Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles btnQuery.Click

        '第一行組合關係為空
        If cmbRelation1.Text = "" Then
            '判斷第一行控制元件內容是否為空
            If cmbField1.Text = "" Then
                MsgBox("請輸入欄位名")

            ElseIf cmbOperation1.Text = "" Then
                MsgBox("請輸入操作符")

            ElseIf txtContent1.Text = "" Then
                MsgBox("請輸入要查詢的內容")

            End If
        End If

        ' 當第一個組合關係不為空時  
        If cmbRelation1.Text <> "" Then
            If cmbField1.Text = "" Then
                MsgBox("請輸入欄位名")
            ElseIf cmbOperation1.Text = "" Then
                MsgBox("請輸入操作符")
            ElseIf txtContent1.Text = "" Then
                MsgBox("請輸入要查詢的內容")
            ElseIf cmbField2.Text = "" Then
                MsgBox("請輸入欄位名")
            ElseIf cmbOperation2.Text = "" Then
                MsgBox("請輸入操作符")
            ElseIf txtContent2.Text = "" Then
                MsgBox("請輸入要查詢的內容")
            End If
        End If

        ' 當第二個組合關係不為空時  
        If cmbRelation2.Text <> "" Then
            If cmbField1.Text = "" Then
                MsgBox("請輸入欄位名")
            ElseIf cmbOperation1.Text = "" Then
                MsgBox("請輸入操作符")
            ElseIf txtContent1.Text = "" Then
                MsgBox("請輸入要查詢的內容")
            ElseIf cmbField2.Text = "" Then
                MsgBox("請輸入欄位名")
            ElseIf cmbOperation2.Text = "" Then
                MsgBox("請輸入操作符")
            ElseIf txtContent2.Text = "" Then
                MsgBox("請輸入要查詢的內容")
            ElseIf cmbField3.Text = "" Then
                MsgBox("請輸入欄位名")
            ElseIf cmbOperation3.Text = "" Then
                MsgBox("請輸入操作符")
            ElseIf txtContent3.Text = "" Then
                MsgBox("請輸入要查詢的內容")
            End If
        End If

        '給實體層傳參
        Dim enGroupQuery As New Model.GroupQueryM
        enGroupQuery._field1 = GetDBName(cmbField1.Text.Trim())
        enGroupQuery._field2 = GetDBName(cmbField2.Text.Trim())
        enGroupQuery._field3 = GetDBName(cmbField3.Text.Trim())
        enGroupQuery._operate1 = cmbOperation1.Text.Trim()
        enGroupQuery._operate2 = cmbOperation2.Text.Trim()
        enGroupQuery._operate3 = cmbOperation3.Text.Trim()
        enGroupQuery._content1 = txtContent1.Text.Trim()
        enGroupQuery._content2 = txtContent2.Text.Trim()
        enGroupQuery._content3 = txtContent3.Text.Trim()
        enGroupQuery._relation1 = GetDBName(cmbRelation1.Text.Trim())
        enGroupQuery._relation2 = GetDBName(cmbRelation2.Text.Trim())
        enGroupQuery.GetTable = GetTable() '通過函式的返回值給引數賦值

        '給B層GroupQuery方法傳遞引數
        Dim FGroupQuery As New Facade.GroupQuertFA
        Dim table As DataTable
        table = FGroupQuery.GroupQuery(enGroupQuery)

        If table.Rows.Count = 0 Then
            MsgBox("沒有記錄,請重新設定查詢條件", vbOKOnly, vbExclamation)
            DataGridView1.DataSource = Nothing
        Else
            DataGridView1.DataSource = FGroupQuery.GroupQuery(enGroupQuery)
        End If
    End Sub

    ' 定義虛擬函式GetDBName,獲取不同資料庫的欄位名  
    Protected Overridable Function GetDBName(ByVal control As String) As String
        Return ""
    End Function

    ' 定義虛擬函式GetDBName,獲取不同資料庫的表名  
    Protected Overridable Function GetTable() As String
        Return ""
    End Function
    Private Sub Button2_Click_1(sender As Object, e As EventArgs) Handles btnExit.Click
        Me.Close()
    End Sub

    '組合關係一不為空後,顯示第二行查詢條件
    Private Sub cmbRelation1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbRelation1.SelectedIndexChanged
        cmbField2.Enabled = True
        cmbOperation2.Enabled = True
        cmbRelation2.Enabled = True
        txtContent2.Enabled = True
    End Sub

    '組合關係二不為空後,顯示第三行查詢條件
    Private Sub cmbRelation2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbRelation2.SelectedIndexChanged
        cmbField3.Enabled = True
        cmbOperation3.Enabled = True
        txtContent3.Enabled = True
    End Sub

End Class</span>

2,在B層,對D層資料庫的查詢結果做出處理

<span style="font-size:18px;">Imports Charge.IDAL
Imports Charge.Model
Public Class GroupQueryBLL
    ''' <summary>
    ''' 根據組合查詢D層的返回結果,判斷是否有值
    ''' </summary>
    ''' <param name="enGroupQuery"></param>
    ''' <returns>沒有值,不返回任何東西,有,就返回資訊</returns>
    ''' <remarks></remarks>
    Public Function GroupQueryStudent(ByVal enGroupQuery As Model.GroupQueryM) As DataTable
        Dim factory As New Factory.CreateFactory
        Dim IGroupQuery As IGroupQuery = factory.CreateGroupQuery
        Dim table As DataTable = IGroupQuery.GroupQuery(enGroupQuery)

        '檢查D層返回的資料表中是否有資料
        If table.Rows.Count = 0 Then
            Return Nothing
        Else
            Return table
        End If
    End Function
End Class</span>

3,在D層對資料進行查詢

<span style="font-size:18px;">/**********************************************
'類名:SQLGroupQuery
'名稱空間:ChargeDAL
'建立時間:2015/1/5 20:58:39
'建立人:HXX
'修改時間:
'修改人:
'版本號:4.0.30319.18449
'說明:實現組合條件的
'版權:HHX
'/**********************************************
Imports System.Data.SqlClient
Imports System.Data
Imports Charge

Public Class SQLGroupQuery : Implements IDAL.IGroupQuery

    ''' <summary>
    ''' 根據設定的條件,進行資訊查詢
    ''' </summary>
    ''' <param name="enGroupQuery"></param>
    ''' <returns>返回查詢結果資訊的集合</returns>
    Public Function GroupQuery(enGroupQuery As Model.GroupQueryM) As DataTable Implements IDAL.IGroupQuery.GroupQuery
        Dim strSQL As String = "QueryGroup" '呼叫儲存過程  

        Dim prams As SqlParameter() = {New SqlParameter("@cmbField1", enGroupQuery._field1),
                                    New SqlParameter("@cmbField2", enGroupQuery._field2),
                                    New SqlParameter("@cmbField3", enGroupQuery._field3),
                                    New SqlParameter("@cmbOperation1", enGroupQuery._operate1),
                                    New SqlParameter("@cmbOperation2", enGroupQuery._operate2),
                                    New SqlParameter("@cmbOperation3", enGroupQuery._operate3),
                                    New SqlParameter("@txtContent1", enGroupQuery._content1),
                                    New SqlParameter("@txtContent2", enGroupQuery._content2),
                                    New SqlParameter("@txtContent3", enGroupQuery._content3),
                                    New SqlParameter("@cmbRelation1", enGroupQuery._relation1),
                                    New SqlParameter("@cmbRelation2", enGroupQuery._relation2),
                                    New SqlParameter("@tableName", enGroupQuery.GetTable)} '設定引數
        Dim MyHelper As New SqlHelper
        Dim table As New DataTable
        table = MyHelper.ExecSelect(strSQL, CommandType.StoredProcedure, prams)
        Return table
    End Function
End Class</span>
三、在繼承窗體中的應用

在繼承窗體中,需要重寫模板父窗體中的方法,關鍵點有:欄位的轉換,資料表的返回。

<span style="font-size:18px;">  Private Sub FrmOperateWorkLog_Activated(sender As Object, e As EventArgs) Handles Me.Activated
        '避免一個窗體多次開啟,或者開啟多個操作窗體
        Dim frm As Form
        '遍歷打開了的每一個窗體
        For Each frm In Application.OpenForms
            '如果當前窗體不是主窗體或者沒有被開啟過
            If frm.Name <> Me.Name And frm.Name <> FrmMain.Name And frm.Name <> FrmLine.Name Then
                '其他開啟的窗體最小化
                frm.WindowState = 1
            End If
        Next
    End Sub
    Private Sub FrmMaintainInfo_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        '給欄位賦值
        cmbField1.Items.AddRange({"教師", "註冊日期", "註冊時間", "登出日期", "登出時間", "機器名"})
        cmbField2.Items.AddRange({"教師", "註冊日期", "註冊時間", "登出日期", "登出時間", "機器名"})
        cmbField3.Items.AddRange({"教師", "註冊日期", "註冊時間", "登出日期", "登出時間", "機器名"})
        cmbOperation1.Items.AddRange({"=", "<", ">", "<>"})
        cmbOperation2.Items.AddRange({"=", "<", ">", "<>"})
        cmbOperation3.Items.AddRange({"=", "<", ">", "<>"})
        cmbRelation1.Items.AddRange({"與", "或"})
        cmbRelation2.Items.AddRange({"與", "或"})
    End Sub
    '重寫獲得表名方法
    Protected Overrides Function GetTable() As String
        enGroupQuery.GetTable = "TC_WorkLogInfo"
        Return enGroupQuery.GetTable()
    End Function
    '重寫轉換成資料庫欄位方法
    Protected Overrides Function GetDBName(control As String) As String
        Select Case (control)
            Case "教師"
                Return "UserID"
            Case "註冊時間"
                Return "OnTime"
            Case "註冊日期"
                Return "OnDate"
            Case "登出時間"
                Return "OffTime"
            Case "登出日期"
                Return "OffDate"
            Case "機器名"
                Return "Computer"
            Case "或"
                Return "or"
            Case "與"
                Return "and"
            Case Else
                Return ""
        End Select
    End Function
End Class
</span>

到這裡,利用窗體繼承和模板方法進行組合查詢就算是實現了。

四、應用說明
1,這裡的返回型別都是DataTable,如果將其換為List,則就沒有這麼簡單了。還需要多寫一步(儲存過程中),就像返回查詢表格的引數一樣,將查詢表格的引數寫到List中的表。
2,這裡D層的查詢是通過呼叫的儲存過程,對儲存過程的使用和理解,將在下一篇部落格中詳細說明。不過,在這裡可以替換成一種型別,就像是第一次做機房時那樣。例(第一次機房中):

<span style="font-size:18px;">txtSQL = txtSQL & tiaojian(Trim(cobozd1(0).Text)) & Trim(cobocz1(0).Text) & "'" & Trim(txtnr1.Text) & "'" _
                            & " and " _
                            & tiaojian(Trim(cobozd1(1).Text)) & Trim(cobocz1(1).Text) & " '" & Trim(txtnr2.Text) & "'" _
                            & " and " _
                            & tiaojian(Trim(cobozd1(2).Text)) & Trim(cobocz1(2).Text) & " '" & Trim(txtnr3.Text) & "'"</span>
在這裡,也可以將儲存過程,換成一般的文字型別查詢。因為是應用的引數賦值,使用字元拼接的方式,將組合查詢的三個情況看做是一種情況,也是可行的。

五、個人感想

學以致用,學了還要會用才行。剛開始學了設計模式的時候,真的感受不大。但用上了之後,真的覺得很方便。只是在用的過程中有點艱難,不過,把一個個的問題解決了,最後實現了,感覺真的很良好。