上一篇博客中简单介绍了事务处理中各个类从中起到的作用、系统设计中为什么要使用事务的处理,以及最简单的在三层架构中通过传递Transaction作为参数最简单的使用事务。
这一篇博客要介绍最后留下的问题。也就是说能不能有更好的办法,不用每次使用事务处理的时候都要在外观层生产事务,然后再作为参数一层层传到需要使用的D层。
但总觉得这样做实在是太麻烦了。而且编码过程中有的这样的想法。现在实现起来需要改动的东西太多了。整个过程中所使用的类都需要修改。学习大话设计模式让我深刻的理解了一句话“不痴迷,不成功。”有没有简单的办法呢??还是这个问题。给大家留了这么长时间解决了。不知道大家有没有想到办法。今天我给大家分享我的方法。
首先明确一件事。就是事物和数据库连接的关系?上篇博客也有提到。现在我还要提出来,这对我们的设计师非常重要的。
上一篇我是这样解释的:
一个连接可以有多个事务。但一个事物只属于一个连接。连接就好像北京到上海的一条铁路,事务就是铁路上的列出,列车可以只有车头,也可以带有好多车厢,火车包括车头都是要到北京的。但是要是要不整列火车到达北京,要不都没有到达。
只了解这些好像是不够的,我们还需要知道,对事物的处理是要通过连接的。
事物的开始代码:
Dim tran As SqlTransaction
Tran = Conn.BeginTransaction
2.在事物中对数据库进行操作要取得事物操作数据库所使用的连接:
Dim conn As SqlConnection
Conn=Tran.Connection
当然说了这么多。最重要的还是如何实现对SqlTransaction的保存,这样就可以那一层用就直接拿了。。
提供一个最简单的思路:
在三层架构中没一层都可以访问的就是实体层。可以在实体层建立实体类,把外观层获得的SqlTransaction对象保存在这个类中。这样SqlTransaction就不用以参数的形式向下传递了。
代码如下:
实体层
Imports System.Data.SqlClient
Public Class E_TranConn
Public Shared _Tran As SqlTransaction
'获得sqlcommand
Public Shared Function GetCmd() As SqlCommand
Return _Tran.Connection.CreateCommand
End Function
'获得sqlconnection
Public Shared Function GetConn() As SqlConnection
Return _Tran.Connection
End Function
Public Shared Property Tran() As SqlTransaction
Get
Return _Tran
End Get
Set(ByVal Value As SqlTransaction)
_Tran = Value
End Set
End Property
End Class
实体类中的变量方法定义为shared ,其他层需要访问时不必实例化直接访问。
外观层以注销卡为例:
''' <summary>
''' 点击注销按钮
''' </summary>
''' <param name="eCard">eCard实体</param>
''' <param name="eAbsentCard">eAbsentCard实体</param>
''' <returns>是否注销成功</returns>
''' <remarks></remarks>
Public Function AbsentCard(ByVal eCard As E_Card, ByVal eAbsentCard As E_Absentcard) As ArrayList
Dim tran As SqlTransaction
Dim flag As Boolean = False
Dim Conn As SqlConnection
Dim list As New ArrayList
Dim Card As New E_Card
'判断卡号是否存在
If bCardOperation.HaveCard(eCard) = False Then
'卡号不存在处理
Throw New Exception("卡号不存在请重新输入!!")
End If
'判断卡是否正在上机
If bOnComputer.IsOnComputer(eCard) = True Then
'如果卡号正在上机
Throw New Exception("此卡正在上机,无法退卡,请先进行下机操作。")
End If
'把原来卡中的余额取出来,保存到退卡记录中的退卡金额
eAbsentCard.AbsentMoney = bCardOperation.GetCardBalance(eCard).Balance
'设置卡的状态为未使用
eCard.CardStatic = "未使用"
'创建事务的connection链接
Conn = bGetTranConn.GetTranConn()
'创建事务
E_TranConn.Tran = Conn.BeginTransaction
'保存事物到tran
tran = E_TranConn.Tran
Try
'更新卡中余额
bCardOperation.UpdateCardBalance(eCard)
'更新卡的状态
bCardOperation.UpdateCardStatic(eCard)
'插入退卡记录
bAbsentCard.InsertAbsentCard(eAbsentCard)
'提交事务
tran.Commit()
'操作成功返回true
Card.Balance = eAbsentCard.AbsentMoney
list.Add(Card)
Catch ex As Exception
tran.Rollback()
Throw ex
Finally
'关闭事务的connection连接
'bGetTranConn.CloseTranConn()
End Try
Return list
End Function
B层代码:
Imports DALFactory Imports System.Data.SqlClient Imports IDAL Public Class TranConnBll Public dalFactory As New DALFactory.DALFactory #Region "取得数据连接" ''' <summary> ''' 取得数据连接 ''' </summary> ''' <returns>connection链接</returns> ''' <remarks></remarks> Public Function GetTranConn() As SqlConnection Dim iTranConn As IDAL.ITranConnDALSql iTranConn = dalFactory.CreatTranConn Dim conn As SqlConnection conn = iTranConn.GetTranConnDALSql() Return conn End Function #End Region #Region "关闭链接" ''' <summary> ''' 关闭链接 ''' </summary> ''' <remarks></remarks> Public Sub CloseTranConn() Dim iTranConn As IDAL.ITranConnDALSql iTranConn = dalFactory.CreatTranConn iTranConn.CloseTranConnDALSql() End Sub #End Region End Class
D层代码:
#Region "更新卡内余额" ''' <summary> ''' 更新卡内余额 ''' </summary> ''' <param name="eCard">eCard实体</param> ''' <returns>是否更新成功</returns> ''' <remarks></remarks> Public Function UpdateCardBalance(ByVal eCard As Entity.E_Card) As Boolean Implements IDAL.ICardInfoDALSql.UpdateCardBalance Dim _strSql As String = "Update T_Card set _Balance=@Balance where _CardNo=@CardNo" Dim param(1) As SqlParameter param(0) = New SqlParameter("@Balance", eCard.Balance) param(1) = New SqlParameter("@CardNo", eCard.CardNo) Dim blnFlag As Boolean = False blnFlag = s_sqlhelper.ExecuteTranNonQuery(param, _strSql) Return blnFlag End Function #End Region
#Region "更新卡状态" ''' <summary> ''' 更新卡状态 ''' </summary> ''' <param name="eCard">eCard实体</param> ''' <returns>是否更新成功</returns> ''' <remarks></remarks> Public Function UpdateCardStatic(ByVal eCard As Entity.E_Card) As Boolean Implements IDAL.ICardInfoDALSql.UpdateCardStatic Dim _strSql As String = "Update T_Card set _CardStatic=@CardStatic where _CardNo=@CardNo" Dim param(1) As SqlParameter param(0) = New SqlParameter("@CardStatic", eCard.CardStatic) param(1) = New SqlParameter("@CardNo", eCard.CardNo) Dim blnFlag As Boolean = False blnFlag = s_sqlhelper.ExecuteTranNonQuery(param, _strSql) Return blnFlag End Function #End Region
#Region "插入退卡信息" ''' <summary> ''' 插入退卡信息 ''' </summary> ''' <param name="eAbsentCard">eAbsentCard实体</param> ''' <returns>是否插入成功</returns> ''' <remarks></remarks> Public Function InsertAbsentCard(ByVal eAbsentCard As E_Absentcard) As Boolean Implements IDAL.IAbsentCardDALSql.InsertAbsentCard Dim _strSql As String = "insert into T_AbsentCard (_CardNo,_AbsentMoney,_UserNo) values (@CardNo,@AbsentMoney,@UserNo)" Dim param(2) As SqlParameter param(0) = New SqlParameter("@CardNo", eAbsentCard.CardNo) param(1) = New SqlParameter("@AbsentMoney", eAbsentCard.AbsentMoney) param(2) = New SqlParameter("@UserNo", eAbsentCard.UserNo) Dim blnFlag As Boolean = False blnFlag = s_sqlhelper.ExecuteTranNonQuery(param, _strSql) Return blnFlag End Function #End Region
sqlhelper代码:
#Region "单例模式生成数据库连接connection"
Public Shared ReadOnly Property Getconn() As SqlConnection
Get
If (IsNothing(conn)) Then
SyncLock syncRoot
If (IsNothing(conn)) Then
conn = New SqlConnection(dataBase)
conn.Open()
End If
End SyncLock
End If
If (conn.State = ConnectionState.Closed) Then
conn.Open()
End If
If (conn.State = ConnectionState.Broken) Then
conn.Close()
conn.Open()
End If
Return conn
End Get
End Property
#End Region
#Region "新增,删除,修改,具有事务处理功能 "
Public Shared Function ExecuteTranNonQuery(ByVal value() As SqlParameter, ByVal strSql As String) As Boolean
Dim cmd As SqlCommand = E_TranConn.GetCmd
cmd.Transaction = E_TranConn.Tran
cmd.CommandText = strSql
cmd.Parameters.AddRange(value)
Try
Dim i As Object = cmd.ExecuteNonQuery
If i > 0 Then
Return True
Else
Return False
End If
Catch ex As Exception
Throw (ex)
End Try
End Function
#End Region
当然以上的这些只是考虑的本地事务的情况。分布式事务不在研究之列。