重构的机房收费系统是用三层实现的,开始简单的增删改的时候还好说,可是当我做到充值退卡的的时候就发现我必须要学点新东西了,因为如果要进行退卡的画,首先我要把查到的信息插入到退卡表中,还要把卡的状态改成退卡状态,这就需要两条SQL语句,但是如果我写在一个函数中的话,第一,他们执行的顺序我就不能保证,第二,如果执行完插入,可是没有执行修改,那么这个卡还在,这就不是意见轻松的事了,所以这时候就发现好东西了,那就是存储结构和事务。
存储结构和事务
那么先大概介绍一下存储结构吧。复杂的介绍就不写了,我就把他理解成一个带有多条SQL语句的结构,结构是死的,只有语句是活的,那么我们就在死结构中加活语句就可以了。因为一个功能有很多时候不是一条语句可以解决的,所以大家就可以把这些语句多写进去,方法和在程序中写是一样的。
事务呢,他是保证存储结构中的SQL语句按顺序执行,且都执行完,负责都不知行,即使执行了前边的,也会让时间倒流。我们把他理解成一条衣服语句,if 语句1,语句2... else 全不执行 end if,这样是不是理解简单一下,而且用起来,更简单。
如果创建存储过程呢?
右键存储过程,点击新建存储过程,然后照着模版敲就可以了
下面我就把机房收费系统的退卡代码和存储结构,事务给大家展示出来,让大家看看他有多简单。但是因为这个程序我还没有完善,所以这只是基本功能的实现,在我完成系统后,会把完善好的代码为大家呈现上来。
存储过程加事务
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:18px;">USE [jf_Charge] GO /****** Object: StoredProcedure [dbo].[Pro_CancelCard] Script Date: 07/28/2014 19:41:05 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author:孟海滨 -- Create date: 2014-7-27 -- Description: 退卡存储过程 -- ============================================= ALTER PROCEDURE [dbo].[Pro_CancelCard] @Card_ID char(11),@head char(11) --定义参数 AS BEGIN tran --执行事务 SET NOCOUNT ON; DECLARE @SumRowCount INT --申明一个变量,用来判断语句成功了几天。 declare @cancelMoney numeric(18,1) --申明变量 declare @Student_Name char(11) SET @SumRowCount=@@ROWCOUNT Select * from StudentView Where Card_ID=@Card_ID --从视图中获取学生信息 SET @SumRowCount=@SumRowCount+@@ROWCOUNT set @CancelMoney= (Select charge from StudentView Where Card_ID=@Card_ID) --将查到的金额信息复制给@CancelMOney insert into CancelCard_info (Card_ID,CancelMoney,head ) values(@Card_ID,@cancelMoney ,@head ) --向退卡表中插入信息 SET @SumRowCount=@SumRowCount+@@ROWCOUNT update Card_Info set IsExist='YES' where Card_ID=@Card_ID and IsExist='No' --修改Card_info中的状态信息 SET @SumRowCount=@SumRowCount+@@ROWCOUNT IF @SumRowCount=4 BEGIN COMMIT TRAN --如果都执行成功,那么开始执行事务 END ELSE BEGIN ROLLBACK TRANSACTION --如果不成功,会滚到以前,让时间倒流 END </span></span></span>
DAL层
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:18px;">Imports Entity Imports System.Data.SqlClient Public Class SQLServerCancelCard : Implements IDAL.ICancelCard Public Function QueryCancelCard(cancel As CancelCardEntity) As CancelCardEntity Implements IDAL.ICancelCard.QueryCancelCard Return Nothing End Function ''' <summary> ''' 该方法用来退卡并利用存储过程,把退卡信息显示出来,其中需要执行多条语句,包括插入退卡信息 ''' 修改卡信息的是否存在,并对视图的信息进行查询,并显示出来 ''' </summary> ''' <param name="cancel"></param> ''' <returns>返回类型是StudentInfoEntity,因为退卡后显示的信息是需要从Student的信息中调用</returns> ''' <remarks></remarks> Public Function CancelCard(cancel As CancelCardEntity) As StudentInfoEntity Implements IDAL.ICancelCard.CancelCard Dim table As DataTable '定义一个DataTable Dim cancelcardinfo As New Entity.StudentInfoEntity '定义一个实体,用来返回数据 Dim sqlhelper As New SqlHelper Dim User_ID As New PublicUserEnity '公共实体,用来将登录者的姓名赋值给实体的属性 Dim strSQL As String = "Pro_CancelCard" '定义参数,防止SQL注入 Dim paras As SqlParameter() = {New SqlParameter("@Card_ID", cancel.Card_ID), New SqlParameter("@head", cancel.head)} '执行SQL语句,返回Datatable table = sqlhelper.ExecSelect(strSQL, CommandType.StoredProcedure, paras) '如果查询到的table不为空,那么就把他的部分值返回给实体属性,最后在返回实体 If table.Rows.Count <> 0 Then cancelcardinfo.Student_Name = table.Rows(0).Item("Student_Name") cancelcardinfo.Charge = table.Rows(0).Item("Charge") End If '返回实体 Return cancelcardinfo End Function End Class </span></span></span>
SQLHelper
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:18px;"> ''' <summary> ''' 执行查询的操作,(有参),参数不限 ''' </summary> ''' <param name="cmdText">需要执行语句,一般是Sql语句,也有存储过程</param> ''' <param name="cmdType">判断Sql语句的类型,一般都不是存储过程</param> ''' <param name="paras">传入的参数</param> ''' <returns></returns> ''' <remarks></remarks> Public Function ExecSelect(ByVal cmdText As String, ByVal cmdType As CommandType, ByVal paras As SqlParameter()) As DataTable Dim sqlAdapter As SqlDataAdapter Dim dt As New DataTable Dim ds As New DataSet '还是给cmd赋值 cmd.CommandText = cmdText cmd.CommandType = cmdType cmd.Connection = conn cmd.Parameters.AddRange(paras) '参数添加 sqlAdapter = New SqlDataAdapter(cmd) '实例化adapter Try sqlAdapter.Fill(ds) '用adapter将dataSet填充 dt = ds.Tables(0) 'datatable为dataSet的第一个表 cmd.Parameters.Clear() '清除参数 Catch ex As Exception MsgBox("查询失败", CType(vbOKOnly + MsgBoxStyle.Exclamation, MsgBoxStyle), "警告") Finally '最后一定要销毁cmd Call CloseCmd(cmd) End Try Return dt End Function</span></span></span>
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:18px;">Imports System.Configuration Imports System.Reflection '添加配置文件引用 Imports IDAL Public Class DataAccess '配置文件,抽象工厂 Private ReadOnly assemblyName As String = "DAL" Private ReadOnly db As String = ConfigurationManager.AppSettings("DB") Dim ClassName As String '创建退卡的抽象工厂 Public Function CreateOnline() As IDAL.IOnline ClassName = assemblyName + "." + db + "CancelCardDAL" Return CType(Assembly.Load(assemblyName).CreateInstance(ClassName), ICancelCard) End Function End Class </span></span></span>
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:18px;"><?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <appSettings> <add key="strCnn" value="server=***.***.**.***;database=jf_Charge;uid=sa;pwd=123456" /> <add key="DB" value="SQLServer"/> </appSettings> </configuration></span></span></span>