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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强制返回为文本 -------------------------------- 数字类型的格式化 --------------------------------     固定格式参数:     General Number 普通数字,如可以用来去掉千位分隔号     format$("100,1
VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办法, Format 或者FormatDateTime 竟然结果和系统设置的区域语言的日期和时间格式相关。意思是尽管你用诸如 Format(Now, "MM/dd/yyyy"),如果系统的设置格式区域语言的日期和时间格式分隔符是"-",那他还会显示为 MM-dd-yyyy     只有拼凑: <%response.write
在项目中添加如下代码:新建窗口来显示异常信息。 Namespace My ‘全局错误处理,新的解决方案直接添加本ApplicationEvents.vb 到工程即可 ‘添加后还需要一个From用来显示错误。如果到这步还不会则需要先打好基础啦 ‘======================================================== ‘以下事件
转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用的爽呀,这篇文章写与2011年,看来我以前没有认真去找这个方法呀。 https://blog.csdn.net/chzjxgd/article/details/6176325 金蝶K3 BOS的插件官方是用VB6编写的,如果  能用.Net下的语言工具开发BOS插件是一件很愉快的事情,其中缘由不言而喻,而本文则是个人首创,实现在了用V
Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选中的单元格进行处理 Dim m As Range, tmpStr As String, s As String Dim x As Integer, y As Integer, subStr As String If MsgBox("确定要分列处理吗?请确定分列的数据会覆盖它后面的单元格!", _
  窗体代码 1 Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) 2 Dim path As String, hash As String 3 For Each fil
  Imports MySql.Data.MySqlClient Public Class Form1 ‘ GLOBAL DECLARATIONS Dim conString As String = "Server=localhost;Database=net2;Uid=root;Pwd=123456;" Dim con As New MySqlConnection
‘導入命名空間 Imports ADODB Imports Microsoft.Office.Interop   Private Sub A1() Dim Sql As String Dim Cnn As New ADODB.Connection Dim Rs As New ADODB.Recordset Dim S As String   S = "Provider=OraOLEDB.Oracl
Imports System.IO Imports System.Threading Imports System.Diagnostics Public Class Form1 Dim A(254) As String    Function ping(ByVal IP As Integer) As String Dim IPAddress As String IPAddress = "10.0.
VB运行EXE程序,并等待其运行结束 参考:https://blog.csdn.net/useway/article/details/5494084 Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long Pr
今天碰到一个问题,登陆的时候,如果不需要验证手机号为空,则不去验证手机号 因为登陆的时候所有的验证信息都存放在一个数组里 Dim CheckUserInfo() As String ={UserBirthday, SecEmail, UserMob, UserSex, RealNameFirst, RealName, CheckCardID, CheckCardType, Contactemail
在VB6.0中,数据访问接口有三种: 1、ActiveX数据对象(ADO) 2、远程数据对象(RDO) 3、数据访问对象(DAO) 1.使用ADO(ActiveX Data Objec,ActiveX数据对象)连接SQL Server 1)使用ADO控件连接 使用ADO控件的ConnectionString属性就可以连接SQL Server,该属性包含一个由分号分隔的argument=value语
注:大家如果没有VB6.0的安装文件,可自行百度一下下载,一般文件大小在200M左右的均为完整版的软件,可以使用。   特别提示:安装此软件的时候最好退出360杀毒软件(包括360安全卫士,电脑管家等,如果电脑上有这些软件的话),因为现如今的360杀毒软件直接会对VB6.0软件误报,这样的话就可能会在安装过程中被误报阻止而导致安装失败,或者是安装后缺乏很多必须的组件(其它的杀毒软件或安全卫士之类的
Private Sub Form_Load() Call conndb End Sub Private Function conndb() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim strCn, sql As String Dim db_host As String Dim db_user As String
  PPSM06S70:  Add  moddate  EDITSPRINTJOB:  MAX(TO_CHAR(ETRN.MODDATE, ‘yyyy/mm/dd/HH24:MI AM‘)) ACTUAL_SHIPDATE   4.Test Scenario (1) :Query SQL Test DN:8016578337 SELECT CTRN.TKCTID TRUCK_ID,        
  沒有出現CrystalReportViewer時,須安裝CRforVS_13_0. 新增1個數據集,新增1個數據表,添加二列,列名要和資料庫名一樣. 修改目標Framework 修改app.config, <startup >改成<startup useLegacyV2RuntimeActivationPolicy ="true">  CrystalReport1.rpt增加數據庫專家 在表單
Imports System.Threading Imports System Public Class Form1 Dim th1, th2 As Thread Public Sub Method1() Dim i As Integer For i = 1 To 100 If Me.Label1.BackColor =
Friend Const PROCESS_ALL_ACCESS = &H1F0FFF = 2035711 Friend Const PROCESS_VM_READ = &H10 Friend Const PROCESS_VM_WRITE = &H20 Friend Const PAGE_READONLY = &H2 Friend Const PAGE_READWRITE = &H4 Friend
以下代码随手写的 并没有大量测试 效率也有待提升 如果需要C#的请自行转换 Function SplitBytes(Data As Byte(), Delimiter As Byte()) As List(Of Byte()) Dim i = 0 Dim List As New List(Of Byte()) Dim bytes As New
Imports System.Data.SqlClient Public Class Form1 REM Public conn1 As SqlConnection = New SqlConnection("server=.; Integrated Security=False;Initial Catalog= mydatabase1; User ID= sa;password")