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

上篇博文给大家一起讨论了实现组合查询的一种方法,即在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 ‘[email protected] [email protected] + char(39) + @content1  +char(39)
if (@relation1 is not null )
set @tempSql [email protected] [email protected] +char(32)[email protected] [email protected] +char(39) [email protected]  +char(39)
if (@relation2 is not null)
set @tempSql [email protected] [email protected] +char(32) [email protected] [email protected] +char(39)[email protected]  +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

最后总结一下组合查询的功能实现:单纯来看这个功能看起来非常高级,能够任意组合你的筛选条件,可是它的实现事实上非常easy,其核心就是将用户输入的限制条件进行拼接和组装,形成Select语句的where子句,然后调用系统函数运行这条SQL语句,将结果返回。难点就是在细节的处理上。即怎样将用户输入的限制条件放入到SQL语句中。这就是我对组合查询的认识。事实上代码实现并非最重要的。重要的是思想上的思考,怎样将问题简化。而且加以实现才是我们学习的核心。

时间: 2024-10-02 02:08:51

重构之路 组合查询之传參+存储过程的相关文章

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

上篇博文给大家一起讨论了实现组合查询的一种方法,即在U层将select语句的where子句部分组装好,赋给一个字符串变量,传到D层然后与select子句组成完整的sql语句,之后执行,返回查询结果,就是这么简单,但是博文的结尾也留下了一个疑问,这种方法的安全性有点欠佳,有没有相对好一点的办法呢? 答案是肯定的,这次我们一起来看看我实现的另一种方法.首先给大家简单介绍一下这种方法的思路,其实也比较简单,最初我是想在程序代码里写sql查询语句的,然后将组合查询的各个条件的值当做实体参数(现在实体层定

重构之路 组合查询之传递SQL字符串

既然是使用VB.NET语言对机房收费系统进行重构,那么无可避免的要去解决组合查询的问题,在VB版的实现中这是一个难点,不过大家还是依靠自己或者共同的智慧解决了这个看似复杂的问题. 如今编程的语言不同是一方面,更重要的是系统的结构不一样了,采用了三层架构去实现系统,这样一来就要考虑组合查询的在三层结构中的实现方法.当然,组合查询的核心办法是不变的,都是通过将查询的各个条件组装成SQL查询语句的where子句来实现的,问题就是这个where子句的组装在哪里完成? 如果放在U层完成,那么我们向下传递的

重构—组合查询

组合查询是重构中的一个重点,也是比较麻烦的,但是我们可以用一个很好的办法来解决它,比如窗体继承,模板方法.关于窗体继承请参考博文:http://blog.csdn.net/augus3344/article/details/29384877 讲的很详细.这里主要说下模板方法,用这个方法可以为我们省掉很多繁琐的步骤和重复的代码.我们就以父窗体为模板,继承窗体来实现不同的模板,也就是将公共的代码写到模板中,自己特有的代码写到自己的模块,下面看代码. 父窗体的代码 U层代码 ImportsSystem

机房重构(5)——模板方法实现组合查询

在敲机房收费过程中,我们会发现很多窗体除了一些细微的差别外,基本是一模一样的,功能的实现也是大同小异.在第一次机房收费的时候,我们都是"好学生",尽管代码重复率极高,还是按部就班的一个个的实现.但在学习了设计模式,机房重构的现在,再傻傻的重复代码,就不是明智之举了. 整个收费系统中,总计有四个组合查询的功能(界面如图),为了提高代码复用率,提高效率,就引入了模板方法实现. 模板方法模式,定义了一个操作中的算法的骨架,把一些步骤延迟到子类当中.它使得子类可以不改变一个算法的结构即可重定义

机房重构---由组合查询引发的思考

前言: 不要基于代码编程,要基于图形进行软件设计. ---米老师 As mentionedabove,是上上个周四晚上锁门时候在小会议室听到米老师给九期师哥师姐讲系统时候的一句话,让我很是触动.Why? 有个问题不知道大家思考过没有,比如在<设计模式>学习过程中,我们照着代码"照葫芦画瓢"似的把代码敲了出来,貌似自己真的懂了,但是真正让自己去实践的时候,我们能做出来吗?或者在敲机房时候,有些难点我们是模仿"前人"博客做出来的,程序能跑起来了,代码自己也理

机房重构之模版方法模式-组合查询

机房收费系统中,一个比较让人纠结功能就是组合查询,不仅仅是代码比较多,而且大多都是重复的代码,也正是因为如此,才比较适合模版方法模式. 一.基本介绍 模版方式模式是定义一个操作中的算法的骨架,而将步骤延迟到子类中. 模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤. 类图 二.具体实现 1.建立模板父窗体 添加Windows窗体,设计模板界面(如下图),并在模板窗体里写入抽象出来的类和方法的代码. '**************************************

组合查询(机房重构知识点总结)

历经n多天,组合查询模板终于做完了,总结一下这几天的成果,和大家一起学习交流. 先看一下父窗体的关键代码: 父窗体代码: Public Class frmComboQuery Protected Overridable Sub frmComboQuery_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim ComboxArray(4) As ComboBox '定义控件数组,获取组合框 ComboxArray(0) = c

组合查询——怎样使用窗口的继承达到事半功倍?

一个优秀的程序猿就是要尽可能降低自己的代码量.我们日常的工作或者学习中都有可能遇到多个窗口结构类似,或者大同小异的情况,这时候假设在每一个窗口都写一遍代码,或者纯粹的复制粘贴就太水了.想要偷懒的时候正是我们发现和创造的机会,我们的祖先也是这么过来的. 我在做机房收费系统个人重构版的时候,就遇到了基本数据维护.查看上机状态.上机信息统计和操作员工作记录四个窗口都组要用到组合查询并且窗口结构一致. 四个窗口中除了字段名不一致,其它的内容都一样,这样的情况下我们用窗口的继承最合适了.在父窗口中写好公共

组合查询——如何使用窗体的继承达到事半功倍?

一个优秀的程序员就是要尽可能减少自己的代码量.我们日常的工作或者学习中都有可能遇到多个窗体结构类似,或者大同小异的情况,这时候如果在每个窗体都写一遍代码,或者纯粹的复制粘贴就太水了.想要偷懒的时候正是我们发现和创造的机会,我们的祖先也是这么过来的. 我在做机房收费系统个人重构版的时候,就遇到了基本数据维护.查看上机状态.上机信息统计和操作员工作记录四个窗体都组要用到组合查询而且窗体结构一致. 四个窗体中除了字段名不一致,其他的内容都一样,这种情况下我们用窗体的继承最合适了.在父窗体中写好公共的部