机房收费系统完美设计——事务处理vs三层架构2

       上一篇博客中简单介绍了事务处理中各个类从中起到的作用、系统设计中为什么要使用事务的处理,以及最简单的在三层架构中通过传递Transaction作为参数最简单的使用事务

 

       这一篇博客要介绍最后留下的问题。也就是说能不能有更好的办法,不用每次使用事务处理的时候都要在外观层生产事务,然后再作为参数一层层传到需要使用的D层。

 

       但总觉得这样做实在是太麻烦了。而且编码过程中有的这样的想法。现在实现起来需要改动的东西太多了。整个过程中所使用的类都需要修改。学习大话设计模式让我深刻的理解了一句话“不痴迷,不成功。”有没有简单的办法呢??还是这个问题。给大家留了这么长时间解决了。不知道大家有没有想到办法。今天我给大家分享我的方法。

 

       首先明确一件事。就是事物和数据库连接的关系?上篇博客也有提到。现在我还要提出来,这对我们的设计师非常重要的。

上一篇我是这样解释的:

       一个连接可以有多个事务。但一个事物只属于一个连接。连接就好像北京到上海的一条铁路,事务就是铁路上的列出,列车可以只有车头,也可以带有好多车厢,火车包括车头都是要到北京的。但是要是要不整列火车到达北京,要不都没有到达。

 

       只了解这些好像是不够的,我们还需要知道,对事物的处理是要通过连接的。

事物的开始代码:

Dim tran As SqlTransaction
Tran = Conn.BeginTransaction

2.在事物中对数据库进行操作要取得事物操作数据库所使用的连接:

Dim conn As SqlConnection
Conn=Tran.Connection

    最后我们还要知道,事务中的所有的操作都必须保证连接处于打开状态,事务处理完毕关闭连接,也就是说,对于不使用事务sqlhelper封装的处理可以直接在sqlhelper里关闭连接。但是对于使用事务的处理必须在使用的那一层关闭,并且保证关闭前对数据库的处理全部完成。否则就会出现如下类似的错误。


当然说了这么多。最重要的还是如何实现对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

    当然以上的这些只是考虑的本地事务的情况。分布式事务不在研究之列。




  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值