上篇博文给大家一起讨论了实现组合查询的一种方法,即在U层将select语句的where子句部分组装好,赋给一个字符串变量,传到D层然后与select子句组成完整的sql语句,之后执行,返回查询结果,就是这么简单,但是博文的结尾也留下了一个疑问,这种方法的安全性有点欠佳,有没有相对好一点的办法呢?
答案是肯定的,这次我们一起来看看我实现的另一种方法。首先给大家简单介绍一下这种方法的思路,其实也比较简单,最初我是想在程序代码里写sql查询语句的,然后将组合查询的各个条件的值当做实体参数(现在实体层定义一个用于组合查询的实体)传进sql语句中,最后再执行sql语句,返回结果。但是后来怎么想也想不出如何组装sql语句,所以就询问别人有没有使用传递参数的组合查询办法,结果人家用的是存储过程,我一想:why not?
下面我们就以查询系统用户工作日志的组合查询功能来看看这种办法的具体实现代码:
首先我们要在实体层Entity定义一个用于组合查询的实体类:
Public Class QueryWorklog
Private _field1 As String
Private _field2 As String
Private _field3 As String
Private _operatorchar1 As String
Private _operatorchar2 As String
Private _operatorchar3 As String
Private _content1 As String
Private _content2 As String
Private _content3 As String
Private _relation1 As String
Private _relation2 As String
Public Property Field1 As String
Get
Return _field1
End Get
Set(value As String)
_field1 = value
End Set
End Property
Public Property Field2 As String
Get
Return _field2
End Get
Set(value As String)
_field2 = value
End Set
End Property
Public Property Field3 As String
Get
Return _field3
End Get
Set(value As String)
_field3 = value
End Set
End Property
Public Property Operatorchar1 As String
Get
Return _operatorchar1
End Get
Set(value As String)
_operatorchar1 = value
End Set
End Property
Public Property Operatorchar2 As String
Get
Return _operatorchar2
End Get
Set(value As String)
_operatorchar2 = value
End Set
End Property
Public Property Operatorchar3 As String
Get
Return _operatorchar3
End Get
Set(value As String)
_operatorchar3 = value
End Set
End Property
Public Property Content1 As String
Get
Return _content1
End Get
Set(value As String)
_content1 = value
End Set
End Property
Public Property Content2 As String
Get
Return _content2
End Get
Set(value As String)
_content2 = value
End Set
End Property
Public Property Content3 As String
Get
Return _content3
End Get
Set(value As String)
_content3 = value
End Set
End Property
Public Property Relation1 As String
Get
Return _relation1
End Get
Set(value As String)
_relation1 = value
End Set
End Property
Public Property Relation2 As String
Get
Return _relation2
End Get
Set(value As String)
_relation2 = value
End Set
End Property
End Class
然后在SQL Server中编写实现组合查询的存储过程:
USE [ChargeSystemDB]
GO
/****** Object: StoredProcedure [dbo].[PROC_QueryWorklog] Script Date: 08/17/2014 22:39:39 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <连江伟>
-- Create date: <2014年8月17号>
-- Description: <用于系统用户工作日志的组合查询>
-- =============================================
ALTER PROCEDURE [dbo].[PROC_QueryWorklog]
-- Add the parameters for the stored procedure here
@field1 char(20),
@field2 char(20),
@field3 char(20),
@operator1 char(20),
@operator2 char(20),
@operator3 char(20),
@content1 char(20),
@content2 char(20),
@content3 char(20),
@relation1 char(20),
@relation2 char(20)
AS
declare @tempSql varchar(500)
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
if (@relation1 ='')
set @relation1 =null
if (@relation2 ='')
set @relation2 =null
--char(32)是空格,char(39)是单引号
set @tempSql ='select * from T_Worklog where '+@field1 +@operator1 + char(39) + @content1 +char(39)
if (@relation1 is not null )
set @tempSql =@tempSql +@relation1 +char(32)+@field2 +@operator2 +char(39) +@content2 +char(39)
if (@relation2 is not null)
set @tempSql =@tempSql +@relation2 +char(32) +@field3 +@operator3 +char(39)+@content3 +char(39)
execute (@tempSql)
END
之后在D层编写函数,调用和执行存储过程并将所需参数传进来:
Public Function QueryWorklog(worklog As QueryWorklog) As List(Of Entity.WorklogEntity) Implements IWorklog.QueryWorklog
Dim mylist As List(Of Entity.WorklogEntity)
Dim mydt As New DataTable
Dim sql As String = "PROC_QueryWorklog"
Dim paras As SqlParameter() = {New SqlParameter("@field1", worklog.Field1),
New SqlParameter("@field2", worklog.Field2),
New SqlParameter("@field3", worklog.Field3),
New SqlParameter("@operator1", worklog.Operatorchar1),
New SqlParameter("@operator2", worklog.Operatorchar2),
New SqlParameter("@operator3", worklog.Operatorchar3),
New SqlParameter("@content1", worklog.Content1),
New SqlParameter("@content2", worklog.Content2),
New SqlParameter("@content3", worklog.Content3),
New SqlParameter("@relation1", worklog.Relation1),
New SqlParameter("@relation2", worklog.Relation2)}
mydt = workloghelper.ExecuteSelect(sql, CommandType.StoredProcedure, paras)
mylist = Entity.ConvertTo.ConvertToList(Of Entity.WorklogEntity)(mydt)
Return mylist
End Function
而后在B层利用接口调用D层的组合查询函数:
Public Function QueryWorklog(ByVal worklog As Entity.QueryWorklog) As List(Of WorklogEntity)
iworklog = fworklog.CreateWorklog
Return iworklog.QueryWorklog(worklog)
End Function
最后在U层将界面中用户的输入内容,赋给实体参数中相应的属性:
Private Sub btnQuery_Click(sender As Object, e As EventArgs) Handles btnQuery.Click
Dim mylist As List(Of Entity.WorklogEntity)
Dim worklog As New Entity.QueryWorklog
Dim Bworklog As New BLL.WorklogBLL
worklog.Field1 = ConvertField(ComboBox1.Text.Trim)
worklog.Field2 = ConvertField(ComboBox2.Text.Trim)
worklog.Field3 = ConvertField(ComboBox3.Text.Trim)
worklog.Operatorchar1 = ComboBox4.Text.Trim
worklog.Operatorchar2 = ComboBox5.Text.Trim
worklog.Operatorchar3 = ComboBox6.Text.Trim
worklog.Content1 = TextBox1.Text.Trim
worklog.Content2 = TextBox2.Text.Trim
worklog.Content3 = TextBox3.Text.Trim
worklog.Relation1 = ComboBox7.Text.Trim
worklog.Relation2 = ComboBox8.Text.Trim
mylist = Bworklog.QueryWorklog(worklog)
If mylist.Count > 0 Then
DataGridView1.DataSource = mylist
Else
MsgBox("未检索到您需要的数据,请重新确认查询条件!", MsgBoxStyle.OkOnly, "提示")
End If
End Sub
最后总结一下组合查询的功能实现:单纯来看这个功能看起来很高级,可以随意组合你的筛选条件,但是它的实现其实非常简单,其核心就是将用户输入的限制条件进行拼接和组装,形成Select语句的where子句,然后调用系统函数执行这条SQL语句,将结果返回,难点就是在细节的处理上,即如何将用户输入的限制条件放入到SQL语句中。这就是我对组合查询的认识,其实代码实现并不是最重要的,重要的是思想上的思考,如何将问题简化,并且加以实现才是我们学习的核心。