以前,再用vb6做机房收费系统的时候,组合查询是一个难点。很不容易理解,但是作完之后会有一种特别舒服的感觉。加入三层架构之后的机房收费系统,我只能说,更加的灵活了。
在进行组合查询之前,在做其余的窗体的时候,在UBD三层之间进行数据交换的时候,所有的数据都是以Entiy传参数的。当然返回值有表也有实体。这里面的优劣暂时不讨论。
就因为,有以上思路之后。当计划组合查询的时候,突然感觉有点发怵。那么多的参数需要传入B层,数据的连续赋值是一个很低级的想法。但此之前,也要有自己的思路。
首先说一下,第一个思路。写一个组合查询的实体。用来传递各个参数。这样做,的确可以达到目的。不管能不能实现,等我先试试再说。这是下面的一种方法。
http://www.jb51.cc/article/p-fsiycwkw-bgd.html
看完涛哥的这篇博客,我感觉代码量太大了。而且里面的代码,有很多重复。仅仅写那一个Entity,我估计就要累死了。我觉得我还是应该化简一下的好。把实体浓缩成三个属性的。
经过反复的斟酌和取舍,最后确定了一种做法,利用四个数组来代替实体。(当然,这四个数组完全可以用集合来代替)
首先说一下,我用数组进行组合查询的思路。
U层:设计组合查询界面,封装窗体上的参数。
B层:由于U层的数据是“姓名”等汉字字段。主要是将U层显示的字段转换成数据库表中的字段。
下面是该实例的界面:
接下来,看一下各层是如何实现各自的职责的。
U层:
- Private Sub btnQuery_Click(sender As Object,e As EventArgs) Handles btnQuery.Click
- '验证所选字段 是否非空
- Dim myObject As New UIcommonFunction
- If myObject.verifyNull(Controls) = False Then
- Exit Sub
- End If
- Try
- Dim dtWorklog As New DataTable '这个表里面存放查询结果
- Dim QueryWorklog As New BLL.sqlQueryRecordBLL
- '定义四个数组,用于存放组合查询的 字段
- Dim fields(2) As String
- Dim operate(2) As String
- Dim content(2) As String
- Dim relation(1) As String
- '把UI上的数据,封装到数组
- fields(0) = cbofield1.Text
- fields(1) = cbofield2.Text
- fields(2) = cbofield3.Text
- operate(0) = cboOperate1.Text
- operate(1) = cboOperate2.Text
- operate(2) = cboOperate3.Text
- content(0) = txtContent1.Text
- content(1) = txtContent2.Text
- content(2) = txtContent3.Text
- relation(0) = cboRelation1.Text
- relation(1) = cboRelation2.Text '这里的参数如果嫌烦的话,可以利用数组循环。我就不做修改了
- '对操作员员工进行组合查询
- dtWorklog = QueryWorklog.CombineQueryWorklog(fields,operate,content,relation)
- mydatagrid.DataSource = dtWorklog
- Catch ex As Exception
- MessageBox.Show(ex.Message.ToString())
- End Try
- End Sub
B层:
- ''' <summary>
- ''' 操作员工的组合查询
- ''' </summary>
- ''' <param name="field"></param>
- ''' <param name="operate"></param>
- ''' <param name="content"></param>
- ''' <param name="relation"></param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function CombineQueryWorklog(field() As String,operate() As String,content() As String,relation() As String) As DataTable
- Dim iWorklog As IDAL.IWorklog
- iWorklog = Factory.DBFactory.CreateWorklog
- '把UI层传回来的汉字,转换成数据库中对应的字段
- For i = 0 To 2
- If field(i) = "教师" Then field(i) = " UserID "
- If field(i) = "上机日期" Then field(i) = " loginDate "
- If field(i) = "上机时间" Then field(i) = " loginTime "
- If field(i) = "注销日期" Then field(i) = " logoutDate "
- If field(i) = "注销时间" Then field(i) = " logoutTime "
- If field(i) = "机器号" Then field(i) = " computer "
- Next
- For i = 0 To 1
- If relation(i) = "与" Then relation(i) = " and "
- If relation(i) = "或" Then relation(i) = " or "
- Next
- '把要查询的内容 用单引号 (这里需要提醒一点,大家可以去对比一下 UserId='1' 与 UserId=1 这两者的区别)
- For i = 0 To 2
- If content(i) <> "" Then
- content(i) = "'" & content(i) & "'"
- End If
- Next
- Dim dtWorklog As New DataTable
- dtWorklog = iWorklog.CombineQueryWorklog(field,relation)
- If dtWorklog.Rows.Count = 0 Then
- Throw New Exception("查询记录为空")
- End If
- Return dtWorklog
- End Function
D层:
- ''' <summary>
- ''' 操作员工记录 组合查询
- ''' </summary>
- ''' <param name="fields"></param>
- ''' <param name="operate"></param>
- ''' <param name="content"></param>
- ''' <param name="relation"></param>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Function CombineQueryWorklog(fields() As String,relation() As String) As DataTable Implements IDAL.IWorklog.CombineQueryWorklog
- Dim strsql As String = "select identity(int,1,1) as 序号,UserID as 教师ID,loginDate as 登陆日期,loginTime as 登陆时间,logoutDate as 注销日期,logoutTime as 注销时间,computer as 机器号 into #1 from worklog_Info where " & fields(0) & operate(0) & content(0) & relation(0) & fields(1) & operate(1) & content(1) & relation(1) & fields(2) & operate(2) & content(2) & "order by loginDate select * from #1 drop table #1"
- Dim helper As New sqlHelper
- Dim dtWorklog As New DataTable
- dtWorklog = helper.QueryNo(strsql,CommandType.Text) '参考<a target=_blank href="http://blog.csdn.net/zc474235918/article/details/26963237">http://blog.csdn.net/zc474235918/article/details/26963237</a>
- Return dtWorklog
- End Function
- End Class
对于以上查询方式,也并不是唯一,完全可以使用 参数化查询,使用sqlparameter 来完成。
在学习过程中,组合查询这个功能的确很经典。这里很容易就区分老手和新手。就好比大话设计模式中,大鸟让菜鸟写的计算器。(不理解的可以借本书来看看)。
对于新手,写上很多很多的代码也是可以实现这个功能的。毕竟这只是一个查询,只是拼接的有点困难而已。
对于老师,我也就不提了啊,敲得代码越多,就越能体会到这里面的辛酸。简练的代码,那都是血与泪的教训啊。
总之,只要感觉代码写的有重复就肯定可以优化。面向对象的程序设计,就是为了解决这种问题而存在的。用抽象来解决共有问题。这样就可以使代码更优。