还记得第一次做机房的时候做组合查询功能吗?那时候的我从刚开始的一个一个判断,到后面的先是让关系框和后面的条件框不能用,根据条件框的填充情况来决定关系框是否能用。这样一步步的走过来的……
到了第二次的机房重构,我发现之前好多的代码都是重复的,做了那么多的无用功!作为一个优秀的程序员,我们要尽可能的减少自己的代码量,让我们的代码能够复用。这里我们要明白复用可不是复制哦!
在机房中,我们的基本学生信息维护、查看上机状态、上机信息统计和操作员工作记录四个窗体除了字段名不一样以外,几乎一样的,所以我们在做组合查询功能的时候用到了窗体的继承。
窗体的继承就是在父窗体中写好公共的部分,不一致的地方可以写一个虚方法,然后让子类们进行重写这个虚方法。这样,我们就只需要一个U层、一个B层、一个接口和一个抽象工厂,一个D层就可以实现四个窗体各自的功能了。
U层主要用来判断一下各个输入框和选择框是否为空,给实体参数和B层方法传值,定义转换数据库字段的虚方法和获取表名的虚方法。
<span style="font-size:18px;">/************************************************* '作者:邢玉 '小组: '说明:组合查询模板 '创建日期:2015.8.9 '版本号: '**********************************************/ Imports System.Windows.Forms Public Class frmGroupQuery '定义一个保护类型的变量,子窗体也可以访问,以下是另一种写法 'Protected groupcheck As JFEntity.GroupEntity = New JFEntity.GroupEntity() Protected groupcheck As New JFEntity.GroupEntity Private Sub frmGroupQuery_Load(sender As Object, e As EventArgs) Handles MyBase.Load '操作符部分,因为操作符不变,所以在父窗体中加载 cmbOperator1.Items.Add(">") cmbOperator1.Items.Add("<") cmbOperator1.Items.Add("=") cmbOperator1.Items.Add("<>") cmbOperator2.Items.Add(">") cmbOperator2.Items.Add("<") cmbOperator2.Items.Add("=") cmbOperator2.Items.Add("<>") cmbOperator3.Items.Add(">") cmbOperator3.Items.Add("<") cmbOperator3.Items.Add("=") cmbOperator3.Items.Add("<>") '关系 cmbRelations1.Items.Add("与") cmbRelations1.Items.Add("或") cmbRelations2.Items.Add("与") cmbRelations2.Items.Add("或") '当选中datagridview控件就选中行 DataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect Dim i As Integer For i = 0 To DataGridView1.Columns.Count - 1 DataGridView1.Columns(i).Width = DataGridViewAutoSizeColumnMode.AllCells Next End Sub ''' <summary> ''' 清空查询条件和结果 ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub btnclear_Click(sender As Object, e As EventArgs) Handles btnclear.Click cmbFiled1.Text = "" cmbFiled2.Text = "" cmbFiled3.Text = "" cmbOperator1.Text = "" cmbOperator2.Text = "" cmbOperator3.Text = "" txtContent1.Text = "" txtContent2.Text = "" txtContent3.Text = "" cmbRelations1.Text = "" cmbRelations2.Text = "" DataGridView1.DataSource = "" End Sub ''' <summary> ''' 退出 ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub btncancel_Click(sender As Object, e As EventArgs) Handles btncancel.Click Me.Dispose() End Sub Private Sub btninquire_Click(sender As Object, e As EventArgs) Handles btninquire.Click '判断组合框不为空 If cmbRelations1.Text = "" Then '如果第一个组合关系框为空 If cmbFiled1.Text = "" Or cmbOperator1.Text = "" Or txtContent1.Text = "" Then MsgBox("第一行查询条件不能为空!", , "提示") Exit Sub End If End If If cmbRelations1.Text <> "" Then '如果选择了第一个组合关系 If cmbFiled2.Text = "" Or cmbOperator2.Text = "" Or txtContent2.Text = "" Then MsgBox("第二行查询条件不能为空!", , "提示") Exit Sub End If Else If cmbRelations2.Text <> "" Then '选择了第二个组合关系 If cmbFiled1.Text = "" Or cmbOperator1.Text = "" Or txtContent1.Text = "" Or cmbFiled2.Text = "" Or cmbFiled2.Text = "" Or txtContent2.Text = "" Or cmbFiled3.Text = "" Or cmbFiled3.Text = "" Or txtContent3.Text = "" Then MsgBox("第三行查询条件不能为空", , "提示") Exit Sub End If End If End If '给实体赋值 groupcheck.GetTable = GetTable() groupcheck.cmbField1 = GetDBName(cmbFiled1.Text.Trim()) groupcheck.cmbField2 = GetDBName(cmbFiled2.Text.Trim()) groupcheck.cmbField3 = GetDBName(cmbFiled3.Text.Trim()) groupcheck.cmbOperator1 = cmbOperator1.Text.Trim() groupcheck.cmbOperator2 = cmbOperator2.Text.Trim() groupcheck.cmbOperator3 = cmbOperator3.Text.Trim() groupcheck.txtContent1 = txtContent1.Text.Trim() groupcheck.txtContent2 = txtContent2.Text.Trim() groupcheck.txtContent3 = txtContent3.Text.Trim() groupcheck.cmbRelation1 = GetDBName(cmbRelations1.Text.Trim()) groupcheck.cmbRelation2 = GetDBName(cmbRelations2.Text.Trim()) '给外观层方法传递参数 Dim dt As New DataTable Dim Ugroupcheck As New Facade.GroupCheckFacade dt = Ugroupcheck.FGroupCheck(groupcheck) If (dt.Rows.Count = 0) Then MsgBox("没有符合条件的记录!请重新设置查询条件!", , "提示") DataGridView1.DataSource = Nothing Else 'DataGridView1.DataSource = dt Call Todatagridview() End If End Sub '当第一个组合关系框的内容发生改变时对第二行查询框是否可用进行判断 Private Sub cmbRelations1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbRelations1.SelectedIndexChanged cmbFiled2.Enabled = True cmbOperator2.Enabled = True txtContent2.Enabled = True cmbRelations2.Enabled = True End Sub '当第二个组合关系框的内容发生改变时对第二行查询框是否可用进行判断 Private Sub cmbRelations2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbRelations2.SelectedIndexChanged '对控件选择进行限定 cmbFiled3.Enabled = True cmbOperator3.Enabled = True txtContent3.Enabled = True End Sub ''' <summary> ''' 定义虚函数GetDBName,获取不同数据库的字段名 ''' </summary> ''' <returns></returns> ''' <remarks></remarks> Public Overridable Function GetDBName(ByVal control As String) As String Return "" End Function '定义虚函数GetTable,获取不同数据库的表名 Protected Overridable Function GetTable() As String Return "" End Function ''' <summary> ''' 把表显示到datagridview中 ''' </summary> ''' <remarks></remarks> Protected Overridable Sub Todatagridview() DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnMode.AllCells End Sub ''' <summary> ''' 调用模块中的方法,导出Excel表 ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub GroupBox1_Enter(sender As Object, e As EventArgs) Call ExportExcel(DataGridView1) End Sub Private Sub btnExcel_Click(sender As Object, e As EventArgs) Handles btnExcel.Click Call ExportExcel(DataGridView1) End Sub </span>B层
<span style="font-size:18px;">'/***************************************** '类 名 称:GroupCheckBLLvb '命名空间:JFBLL '创建时间:2015/7/27 16:46:57 '作 者:邢玉 '小 组: '修改时间: '修 改 人: '版 本 号:v1.0.0 ’****************************************** Imports IDAL Imports JFEntity Public Class GroupCheckBLLvb ''' <summary>实现工厂和接口的方法 ''' 组合查询,父窗体 ''' </summary> ''' <param name="group"></param> ''' <returns></returns> ''' <remarks></remarks> Public Function GroupCheck(ByVal group As JFEntity.GroupEntity) As DataTable Dim Igroupcheck As IDAL.IGroupCheckDAL Dim table As New DataTable Igroupcheck = Factory.LoginFactory.GroupCheck table = Igroupcheck.IGroupCheck(group) If table.Rows.Count = 0 Then ' Return Nothing 'Else Return table End If Return table End Function End Class </span>
<span style="font-size:18px;">'/***************************************** '类 名 称:SqlGroupCheckDAL '命名空间:JFDAL '创建时间:2015/7/27 16:42:43 '作 者:邢玉 '小 组: '修改时间: '修 改 人: '版 本 号:v1.0.0 ’****************************************** Imports System.Data.SqlClient Imports IDAL Public Class SqlGroupCheckDAL : Implements IGroupCheckDAL '实例化sqlHelper Private SqlHelper As SQLHelper.sqlHelper = New SQLHelper.sqlHelper() Public Function IGroupCheck(ByVal groupcheck As JFEntity.GroupEntity) As DataTable Implements IGroupCheckDAL.IGroupCheck Dim sqlparam As SqlParameter() = {New SqlParameter("@cmbFiled1", groupcheck.cmbField1), New SqlParameter("@cmbFiled2", groupcheck.cmbField2), New SqlParameter("@cmbFiled3", groupcheck.cmbField3), New SqlParameter("@cmbOperator1", groupcheck.cmbOperator1), New SqlParameter("@cmbOperator2", groupcheck.cmbOperator2), New SqlParameter("@cmbOperator3", groupcheck.cmbOperator3), New SqlParameter("@txtContent1", groupcheck.txtContent1), New SqlParameter("@txtContent2", groupcheck.txtContent2), New SqlParameter("@txtContent3", groupcheck.txtContent3), New SqlParameter("@cmbRelation1", groupcheck.cmbRelation1), New SqlParameter("@cmbRelation2", groupcheck.cmbRelation2), New SqlParameter("@tableName", groupcheck.GetTable)} '设置参数 Dim strSql As String = "PROC_GroupQuery" '调用存储过程 table = helper.GetDataTable(strSQL, CommandType.StoredProcedure, prams) Return table End Function End Class</span></span>
<span style="font-size:18px;">-- ============================================= -- Author: 邢玉 -- Create date: 2015/7/27 -- Description: 组合查询 -- ============================================= ALTER PROCEDURE [dbo].[PROC_GroupQuery] -- Add the parameters for the stored procedure here @cmbFiled1 varchar(10), @cmbOperator1 varchar(10), @txtContent1 varchar(10), @cmbFiled2 varchar(10), @cmbOperator2 varchar(10), @txtContent2 varchar(10), @cmbFiled3 varchar(10), @cmbOperator3 varchar(10), @txtContent3 varchar(10), @cmbRelation1 varchar(10), @cmbRelation2 varchar(10), @tableName varchar(20) AS declare @TempSql varchar(500)--临时存放Sql语句 --BEGIN -- SET @TempSql='SELECT * FROM '+@tableName +'WHERE'+@cmbFiled1 +@cmbOperator1 +char(39)+@txtContent1 +char(39) -- if @cmbRelation1 != '' -- BEGIN -- SET @TempSql=@TempSql +@cmbRelation1 +CHAR(32)+@cmbFiled2 +@cmbOperator2 +CHAR (39)+@txtContent2 +CHAR (39) -- if @cmbRelation2 != '' -- BEGIN -- SET @TempSql=@TempSql +@cmbRelation2 +CHAR (32)+@cmbFiled3 +@cmbOperator3 +CHAR (39)+@txtContent3 +char(39) -- end -- end -- EXECUTE(@TempSql) BEGIN SET @TempSql='SELECT * FROM '+@tableName +' WHERE ' +@cmbFiled1 +@cmbOperator1+char(39) + @txtContent1 + char(39) if (@cmbRelation1 != '') BEGIN SET @TempSql=@TempSql+@cmbRelation1+CHAR(32)+@cmbFiled2 +@cmbOperator2+CHAR(39)+@txtContent2+CHAR(39) if (@cmbRelation2 is not null ) BEGIN SET @TempSql=@TempSql+@cmbRelation2+CHAR(32)+@cmbFiled3+@cmbOperator3+CHAR(39)+@txtContent3+CHAR(39) END END EXECUTE(@TempSql) END </span>
<span style="font-size:18px;">'/***************************************** '类 名 称:LoginFactory '命名空间:Factory '创建时间:2015/6/7 16:18:59 '作 者:邢玉 '小 组: '修改时间: '修 改 人: '版 本 号:v1.0.0 ’****************************************** Imports System.Configuration '添加对配置文件的引用 Imports System.Reflection '添加对反射的应用 Imports IDAL Imports System.Data ''' <summary> ''' 实例化一个JFDAL中的GroupCheck表的类 ''' </summary> ''' <returns></returns> ''' <remarks></remarks> Public Shared Function GroupCheck() As IGroupCheckDAL Dim className As String = AssemblyName + "." + db + "GroupCheckDAL" Dim Igroupcheck As IDAL.IGroupCheckDAL Igroupcheck = CType(Assembly.Load(AssemblyName).CreateInstance(className), IGroupCheckDAL) Return Igroupcheck End Function</span>编辑完父窗体之后就是要添加我们继承的子窗体了。
第一步:添加继承窗体:
第二步:选择被继承的窗体:
最后在子类中重写父类的虚方法:
<span style="font-size:18px;">/************************************************* '作者:邢玉 '小组: '说明:组合查询模板 '创建日期:2015.8.9 '版本号: '**********************************************/ Public Class frmStuInfo '重写转换成数据库字段的方法 Public Overrides Function GetDBName(control As String) As String Select Case (control) Case "卡号" Return "cardID" Case "学号" Return "studentID" Case "姓名" Return "studentName" Case "性别" Return "sex" Case "系别" Return "department" Case "年级" Return "grade" Case "班级" Return "class" Case "与" Return "and" Case "或" Return "or" Case Else Return "" End Select End Function '重获表名的方法 Protected Overrides Function GetTable() As String groupcheck.GetTable = "Student_Info" Return groupcheck.GetTable End Function Private Sub frmStuInfo_Load(sender As Object, e As EventArgs) Handles MyBase.Load cmbFiled1.Items.Add("学号") cmbFiled1.Items.Add("姓名") cmbFiled1.Items.Add("性别") cmbFiled1.Items.Add("系别") cmbFiled1.Items.Add("年级") cmbFiled1.Items.Add("班级") cmbFiled2.Items.Add("学号") cmbFiled2.Items.Add("姓名") cmbFiled2.Items.Add("性别") cmbFiled2.Items.Add("系别") cmbFiled2.Items.Add("年级") cmbFiled2.Items.Add("班级") cmbFiled3.Items.Add("学号") cmbFiled3.Items.Add("姓名") cmbFiled3.Items.Add("性别") cmbFiled3.Items.Add("系别") cmbFiled3.Items.Add("年级") cmbFiled3.Items.Add("班级") End Sub Protected Overrides Sub Todatagridview() Dim table As New DataTable Dim frmGroupQuery As New frmGroupQuery Dim FacadeGroupQuery As New Facade.GroupCheckFacade Try table = FacadeGroupQuery.FGroupCheck(groupcheck) If table.Rows.Count = 0 Then table.Clear() DataGridView1.DataSource = Nothing DataGridView1.Refresh() Else DataGridView1.DataSource = table 'DataGridView1.Columns(0).Visible = False DataGridView1.Columns(0).HeaderText = "学号" DataGridView1.Columns(1).HeaderText = "姓名" DataGridView1.Columns(2).HeaderText = "系别" DataGridView1.Columns(3).HeaderText = "系别" DataGridView1.Columns(4).HeaderText = "年级" DataGridView1.Columns(5).HeaderText = "班级" End If Catch ex As Exception MsgBox(ex.Message, vbOKOnly, "提示") End Try End Sub End Class </span>我们组合查询的逻辑就是首先只让第一行的条件框可用,关系框和其他的条件框都不可用,只有当第一行的条件框填满的时候,第一个关系框才能用,只有第一个关系框选择了关系之后,第二行的条件框才能用。以此类推……这样我们就省了好多次的判断语句,代码又少了,而且逻辑也清晰了。
我们的每一次将就就是在阻止自己的进步,只有不将就才是发现的源动力!