以前,再用vb6做机房收费系统的时候,组合查询是一个难点。很不容易理解,但是作完之后会有一种特别舒服的感觉。加入三层架构之后的机房收费系统,我只能说,更加的灵活了。
在进行组合查询之前,在做其余的窗体的时候,在UBD三层之间进行数据交换的时候,所有的数据都是以Entiy传参数的。当然返回值有表也有实体。这里面的优劣暂时不讨论。
就因为,有以上思路之后。当计划组合查询的时候,突然感觉有点发怵。那么多的参数需要传入B层,数据的连续赋值是一个很低级的想法。但此之前,也要有自己的思路。
首先说一下,第一个思路。写一个组合查询的实体。用来传递各个参数。这样做,的确可以达到目的。不管能不能实现,等我先试试再说。这是下面的一种方法。
http://blog.csdn.net/dreamcatchergo/article/details/7317250
看完涛哥的这篇博客,我感觉代码量太大了。而且里面的代码,有很多重复。仅仅写那一个Entity,我估计就要累死了。我觉得我还是应该化简一下的好。把实体浓缩成三个属性的。
经过反复的斟酌和取舍,最后确定了一种做法,利用四个数组来代替实体。(当然,这四个数组完全可以用集合来代替)
首先说一下,我用数组进行组合查询的思路。
U层:设计组合查询界面,封装窗体上的参数。
B层:由于U层的数据是“姓名”等汉字字段。主要是将U层显示的字段转换成数据库表中的字段。
D层:进行数据库 查询,之后返回查询结果。
下面是该实例的界面:
接下来,看一下各层是如何实现各自的职责的。
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, operate, content, 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, operate() As String, content() 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 来完成。
在学习过程中,组合查询这个功能的确很经典。这里很容易就区分老手和新手。就好比大话设计模式中,大鸟让菜鸟写的计算器。(不理解的可以借本书来看看)。
对于新手,写上很多很多的代码也是可以实现这个功能的。毕竟这只是一个查询,只是拼接的有点困难而已。
对于老师,我也就不提了啊,敲得代码越多,就越能体会到这里面的辛酸。简练的代码,那都是血与泪的教训啊。
总之,只要感觉代码写的有重复就肯定可以优化。面向对象的程序设计,就是为了解决这种问题而存在的。用抽象来解决共有问题。这样就可以使代码更优。