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

既然是使用VB.NET语言对机房收费系统进行重构,那么无可避免的要去解决组合查询的问题,在VB版的实现中这是一个难点,不过大家还是依靠自己或者共同的智慧解决了这个看似复杂的问题。

如今编程的语言不同是一方面,更重要的是系统的结构不一样了,采用了三层架构去实现系统,这样一来就要考虑组合查询的在三层结构中的实现方法。当然,组合查询的核心办法是不变的,都是通过将查询的各个条件组装成SQL查询语句的where子句来实现的,问题就是这个where子句的组装在哪里完成?

如果放在U层完成,那么我们向下传递的参数就是SQL语句的字符串了,如果放在D层完成,那么我们就要将U层输入的字段内容,操作符号和查询内容当做参数传到D层,然后在D层完成组装,最后调用SQLHelper中的函数执行SQL语句,将结果返回即可,就这么简单。下面我们先来看传SQL语句字符串的解决方案:

首先是U层的代码,U层我们主要完成的是将用户输入的内容进行转换和拼接,形成字符串作为参数向下传递。因为用户输入的字段名称和逻辑关系符号都是汉字的形式,而SQL语句中都为英文形式,必须进行转换,考虑到很多窗体都要使用,因此将转换字段名称和逻辑关系符号封装为两个函数,放在U层的模块中,方便调用,具体实现如下:

ModelUI的两个转换函数:

    ''' <summary>
    ''' 该函数的功能主要是将用户输入的汉字形式的字段名转换为英文形式的字段名称,即数据库中对应的字段名称
    ''' </summary>
    ''' <param name="str"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ConvertField(ByVal str As String) As String
        Dim result As String = ""
        Select Case (str)
            Case "卡号"
                result = "cardID"
            Case "学号"
                result = "studentID"
            Case "姓名"
                result = "studentName"
            Case "性别"
                result = "sex"
            Case "专业"
                result = "major"
            Case "班级"
                result = "classname"
            Case "上机日期"
                result = "onDate"
            Case "机器号"
                result = "computer"
            Case "下机日期"
                result = "offDate"
            Case "消费金额"
                result = "consume"
            Case "用户名"
                result = "userName"
            Case "登录日期"
                result = "loginDate"
            Case "注销日期"
                result = "logoutDate"

        End Select
        Return result

    End Function
    ''' <summary>
    ''' 该函数的主要功能是将用户输入的汉字形式的逻辑关系符号转为SQL语言中的英文形式
    ''' </summary>
    ''' <param name="str"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ConvertLogic(ByVal str As String) As String
        Dim result As String = ""
        Select Case (str)
            Case "或"
                result = " or "
            Case "与"
                result = " and "
        End Select
        Return result

    End Function

U层窗体frmStudentInfo的btnQuery的单击事件代码:

 Private Sub btnQuery_Click(sender As Object, e As EventArgs) Handles btnQuery.Click
        btnModify.Enabled = True
        Dim mylist As New List(Of Entity.QueryBalanceEntity)
        Dim Bstudent As New BLL.StudentBLL
        Dim sqlstr As String = Nothing

        '拼接sql字符串,完成参数sqlstr的赋值操作
        If comboLogic1.Text.Trim = "" Then
            sqlstr = ConvertField(comboField1.Text.Trim) + comboOperator1.Text.Trim + "'" + txtContent1.Text.Trim + "'"
        Else
            sqlstr = ConvertField(comboField1.Text.Trim) + comboOperator1.Text.Trim + "'" + txtContent1.Text.Trim + "'" _
                + ConvertLogic(comboLogic1.Text.Trim) + ConvertField(comboField2.Text.Trim) + comboOperator2.Text.Trim + "'" + txtContent2.Text.Trim + "'"
            If comboLogic2.Text.Trim <> "" Then
                sqlstr = ConvertField(comboField1.Text.Trim) + comboOperator1.Text.Trim + "'" + txtContent1.Text.Trim + "'" _
                + ConvertLogic(comboLogic2.Text.Trim) + ConvertField(comboField2.Text.Trim) + comboOperator2.Text.Trim + "'" + txtContent2.Text.Trim + "'" _
                + ConvertLogic(comboLogic2.Text.Trim) + ConvertField(comboField3.Text.Trim) + comboOperator3.Text.Trim + "'"+ txtContent3.Text.Trim+"'"
            End If

        End If
        '使用B层的实例对象调用B层的函数完成查询
        mylist = Bstudent.QueryStudent(sqlstr)
        If mylist.Count > 0 Then
            DataGridView1.DataSource = mylist
        Else
            MsgBox("未检索到您需要的信息,请重新确认您输入的信息是否有误", MsgBoxStyle.OkOnly, "提示")
        End If

    End Sub

B层相应的函数代码:

    Public Function QueryStudent(ByVal sqlstr As String) As List(Of Entity.QueryBalanceEntity)
        Dim istudent As IStudent
        Dim fstudent As New SQLServerFactory
        istudent = fstudent.CreateStudent
        Return istudent.QueryStudent(sqlstr)

    End Function

D层相应的函数代码:

    Public Function QueryStudent(ByVal sqlstr As String) As List(Of Entity.QueryBalanceEntity) Implements IStudent.QueryStudent
        Dim studentHelper As New SQLHelper.SQLSeverHelper
        Dim mylist As New List(Of Entity.QueryBalanceEntity)
        Dim mydt As New DataTable
        Dim sql As String = "select * from  V_QueryBalance where " + sqlstr

        mydt = studentHelper.ExecuteSelect(sql, CommandType.Text)
        mylist = Entity.ConvertTo.ConvertToList(Of Entity.QueryBalanceEntity)(mydt)

        Return mylist

    End Function

至于上述代码中用来执行SQL语句的ExecuteSelect函数和用来将DataTable转为List泛型集合的ConvertToList函数就不在这里赘述了,相信大家都有自己封装的函数,这里我们主要讨论如何在三层结构中实现组合查询的功能。

最后总结一下这个解决方案,个人觉得这个方法特别简单,也很好理解,传递字符串的想法是我从高迎师姐的博客里看到的,并简化了代码,以自己的形式去重新书写了代码。但是这种方法有一个严重的缺陷,相信了解的人都知道,那就是SQL注入的问题,当然我们可以在输入框中限制用户的输入,从而防止SQl注入问题,但是这样相比较而言,安全性还是差一些,有没有更好的方法呢?         

重构之路 组合查询之传递SQL字符串,布布扣,bubuko.com

时间: 2024-10-09 21:03:09

重构之路 组合查询之传递SQL字符串的相关文章

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

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

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

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

WebForm组合查询

封转类 using System; using System.Collections.Generic; using System.Linq; using System.Web; /// <summary> /// Car 的摘要说明 /// </summary> public class Car { public int ids{get;set;} public string code{get;set;} public string name{get;set;} public st

机房收费系统 之 组合查询BUG

声明:以下内容只对在学生上机记录查询(组合查询)只查询已下机记录,操作员工作记录(组合查询)只查询已注销记录的同学适用! 说是BUG,其实这也不是一个BUG,只是一个不小心容易犯的错误,而且不注意的话还真发现不了.下面就给大家详细的讲讲: 在机房收费系统中有三个组合查询:学生基本信息查询.学生上机记录查询.操作员工作记录查询:其中的学生上机记录查询,我个人认为应该只查询出已经下机的记录,正在上机的记录不应该被查询出来:操作员工作记录也是同样的. 如果你跟我也是一样的想法,那就接着看看我们的实现方

第十七章 组合查询

学习目标: 如何利用UNION操作符将多条SELECT语句组合成一个结果集. 组合查询: 多数SQL查询都只包含从一个或多个表中返回数据的单条SELECT语 句.MySQL也允许执行多个查询(多条SELECT语句),并将结果作为单个 查询结果集返回.这些组合查询通常称为并(union)或复合查询 (compound query). 有两种基本情况,需要使用组合查询: 在单个查询中从不同的表返回类似结构的数据: 对单个表执行多个查询,按单个查询返回数据. 组合查询和多个WHERE条件: 多数情况下

【知识库】-数据库_MySQL之高级数据查询:去重复、组合查询、连接查询、虚拟表

简书作者:seay 文章出处: 关系数据库SQL之高级数据查询:去重复.组合查询.连接查询.虚拟表 回顾:[知识库]-数据库_MySQL之基本数据查询:子查询.分组查询.模糊查询 Learn [已经过测试校验] 一.去重复(DISTINCT) 二.组合查询 三.UNION(并集) 四.连接查询 五.虚拟表 一.去重复(DISTINCT) DISTINCT:用于返回唯一不同的值,主要是用于某一字段 语法 SELECT DISTINCT <列名>|* FROM <表名> 示例 -- 查

重构—组合查询

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

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

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

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

历经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