机房收费系统(VB.NET)——存储过程实战

最初接触存储过程是在耿建玲老师的视频里,当初只是草草过了一遍,只是有了个印象,知道了这个名词;大二时也有SqlServer数据库这门课,不过老师没讲,自己也没看;真正对存储过程的了解来自于自学考试中的《数据库系统原理》,在考试中,知道存储过程是干嘛的,在纸上怎么写,但从来没有在DBMS中亲手敲过。于是机房收费系统给了我这个机会。

在这里不再过多叙述关于存储过程德基本知识,只写一下在机房收费系统这个小项目中是如何用到存储过程的。

背景:

机房收费系统中有一个注册的功能,原型图如下:

注册时,需要对数据库中的三个表进行更新(向卡表T_Card、学生表T_Student、充值表T_Register中分别新增一条记录),所以,执行时,如果用执行SQL语句的方式,那就需要执行三次SQL语句:

1:向卡表T_Card添加记录

 insert into T_Card(cardNumber ,balance ,type ,stuNumber ,status ,isChecked ) values(@cardNumber ,@balance, @type ,@stuNumber ,@status ,@isChecked )

2:向学生表T_Student添加记录

 insert into T_Student (stuNumber,stuName,stuSex,stuMajor,stuGrade,stuClass  ,comment ) values (@stuNumber ,@stuName ,@stuSex ,@stuMajor ,@stuGrade ,@stuClass,@comment )

3:向充值表T_Register添加记录

insert into chargesystem.dbo.T_Recharge (userID,cardNumber,rechargeCash ,rechargeDate ,rechargeTime ,isChecked )values(@userID,@cardNumber ,@balance, CONVERT(varchar,getdate(),120),CONVERT(varchar,GETDATE(),108),'未结账')

存储过程的使用

对于上面的需求,如果用存储过程,在数据库里建立存储过程之后,在代码里只需负责直接执行这个存储过程即可,而不用连续多次连接、操作数据库。

一、建立存储过程

建立存储过程有两种方法(因为系统用的数据库为SqlServer2008,所以这里以此为例):

(1)、手动建立存储过程:

对象资源管理器中:数据库→ChargeSystem(数据库名称)→可编程性→右键“存储过程”→新建存储过程

新建的存储过程可以说是一个已经成型的存储过程德模板,我们只需在上面修改一下存储过程名称、参数、执行语句等代码就OK了。

(2)、SQL语句添加存储过程

直接新建查询,在代码编辑窗口编写存储过程SQL代码,基本语法为:

CREATE  PROCEDURE  PROC_NAME

@[参数名] [类型],@[参数名] [类型]……

AS

BEGIN

[过程体].........

END

用第一种方法建立的存储过程基本上也是这个结构,加入相应的参数和过程体之后,完整的存储过程为:

CREATE PROCEDURE PROC_Register
	-- 定义参数
	@cardNumber varchar(6),@balance decimal(5,1),@type nvarchar(20),@status nvarchar(50),@isChecked nvarchar(10),
	@stuNumber varchar(18),@stuName nvarchar(10),@stuSex varchar(6),@stuMajor nvarchar(30),@stuGrade nvarchar(20),@stuClass nvarchar(20),@comment nvarchar(100),
	@userID varchar(18)
AS
BEGIN

        --向表中插入数据
	insert into ChargeSystem .dbo.T_Card(cardNumber ,balance ,type ,stuNumber ,status ,isChecked ) values(@cardNumber ,@balance, @type ,@stuNumber ,@status ,@isChecked )
	insert into ChargeSystem .dbo.T_Student (stuNumber,stuName,stuSex,stuMajor,stuGrade,stuClass  ,comment ) values (@stuNumber ,@stuName ,@stuSex ,@stuMajor ,@stuGrade ,@stuClass,@comment )
	insert into chargesystem.dbo.T_Recharge (userID,cardNumber,rechargeCash ,rechargeDate ,rechargeTime ,isChecked )values(@userID,@cardNumber ,@balance, CONVERT(char(10),getdate(),120),CONVERT(varchar,GETDATE(),108),'未结账')
END

注意:无论是用哪种方式建立的存储过程,都需要点击执行来存到服务器里,才可以通过以后的调用来执行,单纯地保存(ctrl+C)只是把这个存储过程文件保存在本地,而不会存入数据库服务器中。

二、代码中调用存储过程

调用存储过程跟执行SQL语句的方式大同小异,需要注意的是,执行SQL语句时,命令对象Command的CommandType的值为CommandType.Text,而执行存储过程时,CommandType的值为CommandType.StoredProcedure。

在本例中具体代码为:

D层代码:

Public Class SqlServerRegisterDAL : Implements IDAL.IRegister
    Public Function Insert(ByVal enCard As Entity.CardEntity, ByVal enStudent As Entity.StudentEntity, ByVal userID As String) As Boolean Implements IDAL.IRegister.Insert
        Dim sqlHelper As New SqlHelper                                 '定义SqlHelper实例
        Dim cmdType As CommandType = CommandType.StoredProcedure       '定义数据库命令类型
        Dim cmdText As String = "PROC_Register"                        '数据库执行字符串
        Dim parameters As SqlParameter()                               '定义参数数组,负责向存储过程中的变量传值
        '为参数数组中的参数一一赋值
        parameters = {New SqlParameter("@cardNumber", enCard.CardNumber), New SqlParameter("@balance", enCard.Balance),
                      New SqlParameter("@type ", enCard.CardType), New SqlParameter("@status", enCard.Status),
                      New SqlParameter("@isChecked", enCard.IsChecked), New SqlParameter("@stuNumber", enStudent.StuNumber),
                      New SqlParameter("@stuName", enStudent.StuName), New SqlParameter("@stuSex", enStudent.StuSex),
                      New SqlParameter("@stuMajor", enStudent.StuMajor), New SqlParameter("@stuGrade", enStudent.StuGrade),
                      New SqlParameter("@stuClass", enStudent.StuClass), New SqlParameter("@comment", enStudent.StuComment),
                      New SqlParameter("@userID", userID)}
        '判断是否有查询结果
        If sqlHelper.ExecuteNonQuery(cmdText, cmdType, parameters) Then
            Return True
        Else
            Return False
        End If
    End Function
End Class

SqlHelper代码:

Public Class SqlHelper
    '从配置文件中获取连接字符串的值
    Dim strConnection As String = ConfigurationSettings.AppSettings("strConnection")
    '创建数据库连接对象conn
    Dim conn As SqlConnection
    '创建数据库操作类cmd
    Dim cmd As New SqlCommand

    ''' <summary>
    ''' 构造函数,实例化类时就初始化数据库连接对象
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()
        conn = New SqlConnection(strConnection)
    End Sub

    ''' <summary>
    ''' 关闭释放SqlCommand对象
    ''' </summary>
    ''' <param name="cmd">需要关闭的SqlCommand对象</param>
    ''' <remarks>cmd.Dispose()直接释放command资源,不知这么做对系统性能怎么样,先这么着,以后再继续优化</remarks>
    Public Sub CloseCommand(ByVal cmd As SqlCommand)
        If Not IsNothing(cmd) Then
            cmd.Dispose()
            cmd = Nothing
        End If
    End Sub

    ''' <summary>
    ''' 关闭数据库连接
    ''' </summary>
    ''' <param name="conn">需要关闭的SqlConnection对象</param>
    ''' <remarks>关闭数据库连接,但并没有释放,而是存储在连接池中,需要的时候还可以通过Open()方法打开连接</remarks>
    Public Sub CloseConnection(ByVal conn As SqlConnection)
        If Not IsNothing(conn) Then
            conn.Close()
        End If
    End Sub

    ''' <summary>
    ''' 有参数的 增 删 改 操作
    ''' </summary>
    ''' <param name="cmdText">需要执行的SQL命令</param>
    ''' <param name="cmdType">所执行命令的,一般是sql语句、存储过程或表</param>
    ''' <param name="sqlParameters">参数数组</param>
    ''' <returns>返回受影响的行数 类型为整型</returns>
    ''' <remarks></remarks>
    Public Function ExecuteNonQuery(ByVal cmdText As String, ByVal cmdType As String, ByVal sqlParameters As SqlParameter()) As Integer

       Try
           conn.Open()                                 '打开数据库连接
           cmd.CommandText = cmdText                   '设置查询语句
           cmd.CommandType = cmdType                   '设置一个值,解释cmdType(如果值为StoredProcedure时,调用的是存储过程)
           cmd.Connection = conn                       '设置连接
           cmd.Parameters.AddRange(sqlParameters)      '传入参数

           Dim affectedRows As Integer
           affectedRows = cmd.ExecuteNonQuery
           Return affectedRows                         '返回执行所受影响行数
        Catch ex As Exception
           MsgBox(ex.Message, MsgBoxStyle.OkOnly, "温馨提示")
           Return 0                                    '如果出错,则返回0
        Finally
           cmd.Parameters.Clear()                      '清楚参数
           Call CloseCommand(cmd)                      '关闭并释放Command
           Call CloseConnection(conn)                  '关闭连接conn
        End Try

    End Function
End Class

为什么要使用存储过程

注册学生卡号在这个系统中不算个大模块,但这个小小的需求,需要与数据库中三个表的数据打交道,而在以往的操作,竟然连了三次数据库,执行了三次SQL语句。

这样频繁地打开与关闭与数据库的连接,需要消耗大量系统资源,降低执行速度。这时就需要考虑用存储过程来代替执行如此之多的SQL语句。

1、一般SQL语句每执行一次就需要编译一次,而存储过程只是在创造时进行编译,以后每次执行都不需要再进行编译。

2、存储过程就是相当于把多个需要执行的SQL语句集合起来,变成一条SQL语句,当然就只需连接和执行一次就可以得到结果。

3、安全性高。可以指定存储过程的使用权,防止SQL注入。

4、系统升级、维护比较方便。

总结:

★ 当涉及到多个SQL语句执行,需要多次连接数据库,或者需要对多张表进行处理时,可以将这些操作封装在一起,即创建存储过程,以后每次需要的时候直接调用执行,即可执行所有的操作,避免了多次打开、关闭数据库连接。

★ 当涉及到比较复杂的需求时(比如机房收费系统中的下机结算消费金额就可以采用存储过程),比如排序、计算等等,可以把数据直接传到存储过程,一系列操作在数据库服务器里进行,减小了客户端与服务器之间的数据流量,同时还保证了系统的安全性。

到了这里大家脑子里可能会有个问题:既然让一个存储过程执行多个任务,那么万一在执行的过程中,这些任务中的一个或者几个任务没有完成,该如何是好?这时事务就派上用场了…快去实践吧…

机房收费系统(VB.NET)——存储过程实战

时间: 2024-10-27 13:22:10

机房收费系统(VB.NET)——存储过程实战的相关文章

机房收费系统VB版(一)——系统分析

      首先,我们先回答两个个问题:         1.机房收费系统"是什么"?         2.机房收费系统应该"干什么"?        我的回答:         1.机房收费系统顾名思义就是一个收费系统.         2.机房收费系统主要任务流程是:注册--充值--上机--下机--退卡.而其他的功能都是各个部分人员主要负责的功能.       然后,我们进一步分析一下这个系统的功能. 我们可以把这个系统比作网吧的收费系统,而它的主要面对对象是学

机房收费系统vb.net之打包与部署(二)

紧接着上篇博客的打包和部署,下面说一下我在XP系统和.net framework2.0平台发布系统的解决办法,对于.net framework2.0的情况,因为大家知道如果用visual studio2013的话,最低的运行平台是2.0但是的代码是在4.5的平台下实现的,要是转换过去,会出很多错误,见下图: 生成后的效果就是会出现很多的错误: 原因就是我之前 敲代码的目标框架是默认的4.5,而改成2.0后差异太大,有很多内部编译都发生了变化,因此这种方法是不可以的,下面是我解决这个问题的一个说了

机房收费系统3之存储过程

一,定义 官方定义:是在大型数据库系统中,一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它. 个人理解:对数据库进行复杂操作时,比如对多个表进行Update,Insert,Query,Delete时,对这些复杂操作的SQL语句的封装. 二,基本语法: 1.创建存储过程 基本语法:create procedurepro_name() begin ......... End 注意:过程名:尽量以pro_或者proc_开

机房收费系统重构之存储过程的使用

从一开始对于机房收费系统的无从下手,到现在已经接近尾声,像冬天的迷雾一样,随着时间散开了去,对于其也是越来越清晰,想一想,这种学习的过程还真是美妙. 当然只学习不去总结是没有意义的.今天我就来把存储过程的使用总结一下.拿用户注册来说,就是往数据库里添加用户,以方便更多的用户使用.那么用户注册我们要注意到什么呢? 1.通过卡号判断用户是否已经存在. 如果不存在该用户: 2.将信息写入学生表. 3.更新充值记录表 4.更新卡表中的余额. 我们分析可以得到,如果不存在该用户,我们需要同时改动三个表.当

机房收费系统VB版(四)——上下机

在敲系统的过程中,觉得有点困难的是上下机和结账.当理不清关系,没有头绪的时候,我们先画画图吧,把逻辑理清了,思路自然就有了,不会的再去查就可以了.今天我们就先来分析一下所谓的上下机. 一.上机     上机流程图:     解释说明:    (1)判断文本框的内容是否为空,是否为数字,"否"则弹出提示框: (2)若文本框为数字,判断卡号是否注册,"否"则弹出提示框: (3)若卡号已经注册, 判断卡号是否正在上机,"是"则弹出提示框: (4)若卡号

机房收费系统vb.net之打包与部署(一)

从机房重构到如今,我最大的感受就是万事开头难,万事结尾难!开头难是由于那个思路理不清,对三层已经设计模式的应用不够熟悉,结尾难就是打包部署了!这几天非常头疼,以为完毕了代码就大功告成了,但是没想到啊,打包与部署还easy,由于毕竟是在自己的电脑上64位系统和.net framework4.5的编译平台,没什么可改的,就是一步步来,但是到了XP系统上问题就多了,以下就一一的进行解说: 首先,我的Visual studio是2013版本号的,我就按13版本号将一下打包: 第一步:右击解决方式--"加

机房收费系统VB版(三)——窗体设计

在边建表边敲窗体的过程中,遇到很多问题,所以一边改,一边继续进行,最后将窗体改成下边这个模样. 窗体菜单:  窗体功能分布图: 第一次做的功能分析图: 解释说明: 这次画的图与最初画的系统功能分析图不太一样,但是基本内容没怎么变,只是将权限功能分的更明确一些. (1)将修改密码,帮助,版本信息,退出系统提出来,作为单独的一个"系统"菜单. (2)将结账,日账单,周账单统一放到"结账"二级子菜单下. (3)将"学生上机状态"与"学生上机信

VB.NET版机房收费系统---导出Excel表格

datagridview,翻译成中文的意思是数据表格显示,使用DataGridView控件,可以显示和编辑来自不同类型的数据源的表格,将数据绑定到DataGridView控件非常简单和直观,大多数情况下,只需要设置DataSource属性即可,在绑定到包含多个列表或表的数据库源时,只需将DataMember属性设置为绑定的列表或表的字符串即可.机房收费系统多次用到数据表格的显示,并且导出为Excel表格,第一次机房收费系统是用VB版本的,她导出Excel的方法如下: 打开VB-工程-应用-勾选M

vb.net机房收费系统——存储过程

一.使用背景 机房收费系统结账的时候,需求是当选择一个用户,同时显示该用注册.充值和退卡记录,这些数据来提供结账数据,而结账之后要同时更新卡.充值.退卡表三个表,如果直接写SQl语句的话会是很复杂的.而这些需求可以封装为一个存储过程,点击结账之后只需要传入参数执行存储过程即可. 二.存储过程简介 存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它.存储过程是数据库中的一个