首页 > 代码库 > 重构之路 组合查询之传参+存储过程

重构之路 组合查询之传参+存储过程

         上篇博文给大家一起讨论了实现组合查询的一种方法,即在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语句中。这就是我对组合查询的认识,其实代码实现并不是最重要的,重要的是思想上的思考,如何将问题简化,并且加以实现才是我们学习的核心。