机房收费系统中有三个功能用到了“组合查询”——可以查询1到3个条件的数据。这三胞胎长得是很像很像滴,上图:
学习了设计模式,但是到实际用的时候还是不会啊,看了很多资料博客,在这里实践了一把——用模板方法模式
分析:三个的窗体是一样的,查询的表不一样,字段也就不一样,所以要在抽象出来的父窗体中写一个基本框架,在各自的子窗体中赋值。
1.窗体
父窗体写好以后,子窗体创建:
以“学生信息维护”为例,子窗体与父窗体长的一样,创建好之后控件上有小锁标志,会发现,它是不能动的(事件不可用)
u层代码如下:这里要写一个虚方法,用来返回字段名,在各个子窗体中就可以重写来给字段赋值了
Public Class FrmPowerQuery Private Sub BtnClear_Click(sender As Object, e As EventArgs) Handles BtnClear.Click CmbActor1.Text = "" CmbActor2.Text = "" CmbActor3.Text = "" CmbFieldName1.Text = "" CmbFieldName2.Text = "" CmbFieldName3.Text = "" CmbRelation1.Text = "" CmbRelation2.Text = "" TxtMessage1.Text = "" TxtMessage2.Text = "" TxtMessage3.Text = "" DataGridView1.DataSource = "" End Sub Private Sub BtnOK_Click(sender As Object, e As EventArgs) Handles BtnOK.Click If CmbActor1.Text.Trim = "" Or CmbFieldName1.Text.Trim = "" Or TxtMessage1.Text.Trim = "" Then MsgBox("请将第一行查询信息补充完整") Exit Sub End If If CmbRelation1.Text <> "" And (CmbActor2.Text.Trim = "" Or CmbFieldName2.Text.Trim = "" Or TxtMessage2.Text.Trim = "") Then MsgBox("应该将第二条查询信息补充完整") Exit Sub End If If CmbRelation2.Text <> "" And (CmbActor3.Text.Trim = "" Or CmbFieldName3.Text.Trim = "" Or TxtMessage3.Text.Trim = "") Then MsgBox("应将第三条查询信息补充完整") Exit Sub End If '实体赋值 Dim Queryinfo As New Entity.ePowerQueryEntity Queryinfo.DBName = getDTName() '获取数据库名 Queryinfo.CmbActor1 = SameAsTable(CmbActor1.Text.Trim) '获得查询的字段名并且转化成sql语句可以识别的语句 Queryinfo.CmbActor2 = SameAsTable(CmbActor2.Text.Trim) Queryinfo.CmbActor3 = SameAsTable(CmbActor3.Text.Trim) Queryinfo.CmbFileName1 = SameAsTable(CmbFieldName1.Text.Trim) Queryinfo.CmbFileName2 = SameAsTable(CmbFieldName2.Text.Trim) Queryinfo.CmbFileName3 = SameAsTable(CmbFieldName3.Text.Trim) Queryinfo.CmbRelation1 = SameAsTable(CmbRelation1.Text.Trim) Queryinfo.CmbRelation2 = SameAsTable(CmbRelation2.Text.Trim) Queryinfo.TxtMessage1 = TxtMessage1.Text.Trim Queryinfo.TxtMessage2 = TxtMessage2.Text.Trim Queryinfo.TxtMessage3 = TxtMessage3.Text.Trim Try Dim facade As New Facade.Facade Dim table As DataTable table = facade.PowerQuery(Queryinfo) If table.Rows.Count = 0 Then MsgBox("没有查到任何记录") Else DataGridView1.DataSource = table End If Catch ex As Exception MsgBox("查询过程出错了") End Try End Sub
''' <summary> ''' 虚方法 使得表中填写的字段名与数据库中保持一致 ''' </summary> ''' <param name="cmbFileName"></param> ''' <returns></returns> ''' <remarks></remarks> Protected Overridable Function SameAsTable(cmbFileName As String) As String Return "" End Function
''' <summary> ''' ''' 虚方法 获得数据库的名字 ''' </summary> ''' <returns></returns> ''' <remarks></remarks> Protected Overridable Function getDTName() As String Return "" End Function Private Sub BtnExit_Click(sender As Object, e As EventArgs) Handles BtnExit.Click Me.Close() FrmMain.Show() End Sub Private Sub FrmPowerQuery_Load(sender As Object, e As EventArgs) Handles MyBase.Load 'combo框只能从下拉菜单里面选择不可以输入 CmbActor1.DropDownStyle = 2 CmbActor2.DropDownStyle = 2 CmbActor3.DropDownStyle = 2 CmbFieldName1.DropDownStyle = 2 CmbFieldName2.DropDownStyle = 2 CmbFieldName3.DropDownStyle = 2 CmbRelation1.DropDownStyle = 2 CmbRelation2.DropDownStyle = 2 End Sub End Class学生信息维护 U层代码:
Public Class FrmStudentInfoMaintain1 Private Sub FrmStudentInfoMaintain_Load(sender As Object, e As EventArgs) Handles MyBase.Load CmbFieldName1.Items.Add("卡号") CmbFieldName1.Items.Add("姓名") CmbFieldName1.Items.Add("学号") CmbFieldName1.Items.Add("性别") CmbFieldName1.Items.Add("系别") CmbFieldName1.Items.Add("年级") CmbFieldName1.Items.Add("班级") CmbFieldName2.Items.Add("卡号") CmbFieldName2.Items.Add("姓名") CmbFieldName2.Items.Add("学号") CmbFieldName2.Items.Add("性别") CmbFieldName2.Items.Add("系别") CmbFieldName2.Items.Add("年级") CmbFieldName2.Items.Add("班级") CmbFieldName3.Items.Add("卡号") CmbFieldName3.Items.Add("姓名") CmbFieldName3.Items.Add("学号") CmbFieldName3.Items.Add("性别") CmbFieldName3.Items.Add("系别") CmbFieldName3.Items.Add("年级") CmbFieldName3.Items.Add("班级") End Sub Protected Overrides Function SameAsTable(cmbFileName As String) As String Select Case cmbFileName Case "卡号" SameAsTable = "CardNO" Case "姓名" SameAsTable = "studentName" Case "学号" SameAsTable = "studentNO" Case "性别" SameAsTable = "Sex" Case "系别" SameAsTable = "Department" Case "年级" SameAsTable = "Grade" Case "班级" SameAsTable = "Class" Case "与" SameAsTable = "and" Case "或" SameAsTable = "or" Case "<>" SameAsTable = "<>" Case "<" SameAsTable = "<" Case ">" SameAsTable = ">" Case "=" SameAsTable = "=" Case Else SameAsTable = "" End Select End Function Protected Overrides Function getDTName() As String Return "Student" End Function End Class连接数据库:三个功能中用的表不一样,所以在SQLHelper中添加一个方法,不直接传参,代码如下:
Public Function Query(ByVal cmdText As String, ByVal cmdType As CommandType) As DataTable Dim sqlAdapter As SqlDataAdapter '定义数据适配器) Dim dt As New DataTable Dim ds As New DataSet '给cmd赋值 cmd.CommandText = cmdText 'cmdtext为要执行的sql语句 cmd.CommandType = cmdType '命令执行的类型 cmd.Connection = conn sqlAdapter = New SqlDataAdapter(cmd) '实例化Adapter Try sqlAdapter.Fill(ds) '用adapter将dataset填充 dt = ds.Tables(0) 'datatable为dataSet的第一个表 Catch ex As Exception MsgBox("数据库操作失败") Finally Call CloseCmd(cmd) '销毁cmd命令 End Try Return dt End FunctionD层:
Public Function PowerQuery(ByVal Queryinfo As Entity.ePowerQueryEntity) As DataTable Implements IPowerQuery.PowerQuery Dim sqlinfo As String '用于存放sql语句 Dim table As DataTable Dim sqlhelper As New SQLHelper.sqlHelper Dim cmdtype As CommandType = New CommandType() If Queryinfo.CmbRelation1 = "" Then sqlinfo = "Select * from " & Queryinfo.DBName & " where" & Chr(32) & Queryinfo.CmbFileName1 & Queryinfo.CmbActor1 & "'" & Queryinfo.TxtMessage1 & "'" '@FileName1 @Actor1 @Message1" ElseIf Queryinfo.CmbRelation1 <> "" And Queryinfo.CmbRelation2 = "" Then sqlinfo = "select * from" & Chr(32) & Queryinfo.DBName & Chr(32) & "where" & Chr(32) & Queryinfo.CmbFileName1 & Chr(32) & Queryinfo.CmbActor1 & Chr(32) & "'" & Queryinfo.TxtMessage1 & "'" & Chr(32) & Queryinfo.CmbRelation1 & Chr(32) & Queryinfo.CmbFileName2 & Chr(32) & Queryinfo.CmbActor2 & Chr(32) & "'" & Queryinfo.TxtMessage2 & "'" Else sqlinfo = "select * from" & Chr(32) & Queryinfo.DBName & Chr(32) & "where" & Chr(32) & Queryinfo.CmbFileName1 & Chr(32) & Queryinfo.CmbActor1 & Chr(32) & "'" & Queryinfo.TxtMessage1 & "'" & Chr(32) & Queryinfo.CmbRelation1 & Chr(32) & Queryinfo.CmbFileName2 & Chr(32) & Queryinfo.CmbActor2 & Chr(32) & "'" & Queryinfo.TxtMessage2 & "'" & Chr(32) & Queryinfo.CmbRelation2 & Chr(32) & Queryinfo.CmbFileName3 & Chr(32) & Queryinfo.CmbActor3 & Chr(32) & "'" & Queryinfo.TxtMessage3 & "'" End If table = sqlhelper.Query(sqlinfo, CommandType.Text) Return table End Function
做完组合查询三个功能以后,感觉设计模式确实很神奇,简洁方便。自己写的代码还是有很多重复的地方,有很多漏洞,看别人的博客学到很多方法,开始觉得很难,做完了也就不觉得了,不要被自己吓倒,慢慢积累。