`
caobihole
  • 浏览: 950757 次
文章分类
社区版块
存档分类
最新评论

项目总结——再谈事务机制

 
阅读更多

引言:

做机房收费系统时,有研究过在三层架构中添加事务处理的机制。那时候基本是自创的一个方法。因为要访问一个公共的静态变量。当时自然就想到了使用实体类,这样得到公共的Connection以后就可以不用在每个层中传了。同样这次的系统中也用到了事务机制的处理。发现了另一种使用事务机制的好的方法,当然也要拿出来给大家分享下了。

基本思路:

看代码之前,大概说一下这次系统中使用是如何使用事务机制了。事务无非就是同时执行多条sql语句,要保证事务的实现无非就是让执行这几条sql语句在同一个Connection链接下操作。其实事务很简单,不过是和三层混在了一起所以让人无从下手罢了,这次的系统中实现事务机制的方法是把要同时执行的多条sql语句放在D层的一个方法里。如果多条sql语句都没有参数,那么就只需要把这多条的sql语句保存起来然后再传给sqlhelper逐条的执行,如果多条的sql语句都带有参数,那么需要保存的就不止有sql语句还用其对应的参数了。

技术难点:

看到这里大家发现其实主要的技术难点只剩下两个,

1.保存这些sql语句,以及他们可能有的参数,然后对应的取出来。

2.就是把对应的把sql语句自己的参数附加上去。

代码以及说明:

说到现在我想应该让大家看看代码了:(这里的例子是带有参数的sql语句,这个掌握了,不带参数的自然也就掌握了。)

首先是D层确定需要放在同一个事务中处理的sql语句,并保存起来用于送给sqlhelper处理。

 ''' <summary>
    ''' 注册卡号时的事务,需要向学生表,卡表,充值记录中添加信息--韩义
    ''' </summary>
    ''' <param name="enStuCard">附有所有信息的学生卡实体</param>
    ''' <param name="enRecharge">附有所有信息的充值实体</param>
    ''' <returns>bool,true则表示成功,false则表示失败</returns>
    ''' <remarks></remarks>
    Public Function Register(ByVal enStuCard As Entity.StuCardEntity, ByVal enRecharge As Entity.ChargeEntity) As Boolean Implements IDAL.IAffairsDAL.Register
        Dim HashList As New Hashtable '定义hashtable。
        '第一条需要执行的sql语句,以及他的参数。
        Dim sql1 As String = "insert into T_Card(CardNo,StudentNo,Cash,CardType,Creater,Status,IsCheck,Date,Time) values(@CardNo,@StudentNo,@Cash,@CardType,@Creater,@Status,@IsCheck,@Date,@Time)"
        Dim sqlParam1(8) As SqlParameter
        sqlParam1(0) = SqlHelperDAL.AddSqlParameter("@CardNo", SqlDbType.Char, enStuCard.CardNO)
        sqlParam1(1) = SqlHelperDAL.AddSqlParameter("@StudentNo", SqlDbType.Char, enStuCard.StudentNO)
        sqlParam1(2) = SqlHelperDAL.AddSqlParameter("@Cash", SqlDbType.Decimal, CDec(enStuCard.Cash))
        sqlParam1(3) = SqlHelperDAL.AddSqlParameter("@CardType", SqlDbType.VarChar, enStuCard.CardType)
        sqlParam1(4) = SqlHelperDAL.AddSqlParameter("@Creater", SqlDbType.Char, enStuCard.Creater)
        sqlParam1(5) = SqlHelperDAL.AddSqlParameter("@Status", SqlDbType.Char, enStuCard.Status)
        sqlParam1(6) = SqlHelperDAL.AddSqlParameter("@IsCheck", SqlDbType.Char, enStuCard.IsCheck)
        sqlParam1(7) = SqlHelperDAL.AddSqlParameter("@Date", SqlDbType.Char, enStuCard.RegisterDate)
        sqlParam1(8) = SqlHelperDAL.AddSqlParameter("@Time", SqlDbType.Char, enStuCard.RegisterTime)
        '第二条需要执行的语句,以及他的参数
        Dim sql2 As String = "insert into T_Student(StudentNo,StudentName,Sex,Department,Grade,Class) values(@StudentNo,@StudentName,@Sex,@Department,@Grade,@Class)"
        Dim sqlParam2(5) As SqlParameter
        sqlParam2(0) = SqlHelperDAL.AddSqlParameter("@StudentNo", SqlDbType.Char, enStuCard.StudentNO)
        sqlParam2(1) = SqlHelperDAL.AddSqlParameter("@StudentName", SqlDbType.Char, enStuCard.StudentName)
        sqlParam2(2) = SqlHelperDAL.AddSqlParameter("@Sex", SqlDbType.Char, enStuCard.Sex)
        sqlParam2(3) = SqlHelperDAL.AddSqlParameter("@Department", SqlDbType.VarChar, enStuCard.Department)
        sqlParam2(4) = SqlHelperDAL.AddSqlParameter("@Grade", SqlDbType.Char, enStuCard.Grade)
        sqlParam2(5) = SqlHelperDAL.AddSqlParameter("@Class", SqlDbType.Char, enStuCard.ClassName)

        '第三条需要执行的语句以及他的参数
        Dim sql3 As String = "insert into T_Recharge(CardNo,AddMoney,UserID,IsCheck,Date,Time) values(@CardNo,@AddMoney,@UserID,@IsCheck,@Date,@Time)"
        Dim sqlParam3(5) As SqlParameter
        sqlParam3(0) = SqlHelperDAL.AddSqlParameter("@CardNo", SqlDbType.Char, enRecharge.CardNO)
        sqlParam3(1) = SqlHelperDAL.AddSqlParameter("@AddMoney", SqlDbType.Decimal, CDec(enRecharge.AddMoney))
        sqlParam3(2) = SqlHelperDAL.AddSqlParameter("@UserID", SqlDbType.Char, enRecharge.UserID)
        sqlParam3(3) = SqlHelperDAL.AddSqlParameter("@IsCheck", SqlDbType.Char, enRecharge.IsCheck)
        sqlParam3(4) = SqlHelperDAL.AddSqlParameter("@Date", SqlDbType.Char, enRecharge.ChargeDate)
        sqlParam3(5) = SqlHelperDAL.AddSqlParameter("@Time", SqlDbType.Char, enRecharge.Time)
        '把三条sql语句和对应的参数保存到hashtable中
        HashList.Add(sql1, sqlParam1)
        HashList.Add(sql2, sqlParam2)
        HashList.Add(sql3, sqlParam3)
        Try
            '传递个sqlhelper执行
            SqlHelperDAL.ExecuteSqlTran(HashList)
            Return True
        Catch ex As Exception
            Return False
        End Try
    End Function

这里我们完成注册卡需要同时完成三件事1.注册卡信息。2.注册学生信息。3添加充值记录。
大家通过代码也可以看得出来。代码中我们使用了哈希表保存sql语句以及他们对应的参数,哈希表主要有点是他的存取是键值对型的。想到这个其实我们就解决了问题1.我们现在就可以对应的保存与提取了。
然后我们一起来看sqlheper的代码:

        ''' <summary>
        ''' 执行多条sql语句,实现数据库事务--韩义
        ''' </summary>
        ''' <param name="SQLStringList">sql语句的哈希表</param>
        ''' <remarks></remarks>
        Public Sub ExecuteSqlTran(ByVal SQLStringList As Hashtable)
            Using (conn) '打开数据库连接
                '打开数据库连接  
                conn.Open() '打开数据连接
                Dim trans As SqlTransaction = conn.BeginTransaction() '开始数据库事务
                Using (trans)
                    Try
                        '循环
                        For Each myDE As DictionaryEntry In SQLStringList
                            Dim cmdText As String = myDE.Key.ToString()
                            Dim cmdParms() As SqlParameter = CType((myDE.Value), SqlParameter())
                            PrepareCommand(cmd, conn, trans, cmdText, cmdParms)
                            Dim val As Integer = cmd.ExecuteNonQuery() '调用ExecuteNonQuery函数,返回受影响的行数
                            cmd.Parameters.Clear() '清空参数对象
                        Next
                        trans.Commit() '提交事务
                    Catch ex As Exception
                        trans.Rollback() '事务回滚
                        Throw
                    End Try

                End Using
            End Using
        End Sub


上面的这段代码中包括一个循环,这个循环的主要作用就是取出保存在hashtable中的sql语句以及参数,而且保证不会“乱”。当然这其中还有一个很重要的函数
PrepareCommand这个函数的作用就是把取出来的sql语句和参数,组合在一起。
''' <summary>
        ''' 写入参数--韩义
        ''' </summary>
        ''' <param name="cmd">sqlCommand命令</param>
        ''' <param name="conn">sqlconnection命令</param>
        ''' <param name="trans">事务</param>
        ''' <param name="cmdText">sql语句</param>
        ''' <param name="cmdParms">参数</param>
        ''' <remarks></remarks>
        Public Sub PrepareCommand(ByVal cmd As SqlCommand, ByVal conn As SqlConnection, ByVal trans As SqlTransaction, ByVal cmdText As String, ByVal cmdParms() As SqlParameter)
            If conn.State <> ConnectionState.Open Then
                conn.Open()
            End If
            cmd.Connection = conn '设置连接
            cmd.CommandText = cmdText '设置对数源执行的sql语句
            If Not IsNothing(trans) Then
                cmd.Transaction = trans '设置执行事务
                cmd.CommandType = CommandType.Text
            End If
            If Not IsNothing(cmdParms) Then '如果存在参数
                '遍历每个参数
                For Each parameter As SqlParameter In cmdParms
                    If (parameter.Direction = ParameterDirection.InputOutput Or parameter.Direction = ParameterDirection.Input) And (IsDBNull(parameter.Value)) Then
                        parameter.Value = DBNull.Value '附空值
                    End If
                    cmd.Parameters.Add(parameter) '加入参数
                Next
            End If
        End Sub

这样我们也就解决了第二个问题--就是把对应的把sql语句自己的参数附加上去。

看到这里,事务处理基本已经完成了。对于没有参数的多条sql语句,当然泛型是很好的选择。把多条sql语句保存在一个字符串类型的泛型中,然后向下传递。

总结:

两种在三层中添加事务的处理方式都已经在我的博客中有介绍了。那么让我们来总结,比较一下这两种方法的区别把(另一篇博客地址:http://blog.csdn.net/hy6688_/article/details/8933097)我总结的区别有一下几点:(为了方便说明原来的那篇称第一篇,现在的这篇称第二篇)。
1.第一篇中的方法,没有第二篇的简单、直接。
2.第一篇中的方法可以实现这样的操作:第二条sql语句的执行要依赖与第一条sql语句执行的返回结果。
3.第一篇中的方法把每一个sql语句单独的作为一个方法,这样可以实现简单的复用,如果另一个事务机制的处理需要使用这个方法直接拿来用就可以了。
4.第二篇中的方法,用到的hashtable,方法很巧妙值得学习研究。




分享到:
评论

相关推荐

    云应用开发 ——Google App Engine & Google Web Toolkit入门指南

    7.5 事务 7.6 关系 7.7 实例——员工管理系统 第8章 国际化 8.1 普通文本国际化 8.2 参数文本国际化 8.3 实例 第9章 应用托管 9.1 申请Google App Engine账号 9.2 上传应用 9.3 应用维护指南 第10章 实战 10.1 ...

    asp.net知识库

    也谈 ASP.NET 1.1 中 QueryString 的安全获取写法 ASP.NET运行模式:PageHandlerFactory 利用搜索引擎引用来高亮页面关键字 网站首页的自动语言切换 应用系统的多语言支持 (一) 应用系统的多语言支持 (二) 自动...

    观辰软件OA启航版 v2.5

    计划、任务、分派、执行、报告、总结、发言/点评(自评分、领导评分、桌面当月每日评分/每事评分曲线图)、分析、统计、全面提高日常运营管理活动中任何涉及时间期限安排的事务(合同条款执行、账单缴费、服务项目...

    Spring.3.x企业应用开发实战(完整版).part2

    10.3.1 Spring事务传播机制回顾 10.3.2 相互嵌套的服务方法 10.4 多线程的困惑 10.4.1 Spring通过单实例化Bean简化多线程问题 10.4.2 启动独立线程调用事务方法 10.5 联合军种作战的混乱 10.5.1 Spring事务管理器的...

    Spring3.x企业应用开发实战(完整版) part1

    10.3.1 Spring事务传播机制回顾 10.3.2 相互嵌套的服务方法 10.4 多线程的困惑 10.4.1 Spring通过单实例化Bean简化多线程问题 10.4.2 启动独立线程调用事务方法 10.5 联合军种作战的混乱 10.5.1 Spring事务管理器的...

    禅道项目管理软件ZenTaoPMS源码包-PHP

    更新日志:禅道 12.5.3 版本修改记录完成的需求实现年度总结的Bug数据区块实现区块的鼠标hover态年度总结实现按公司、部分、个人的范围统计实现年度总结的用例数据区块实现年度总结的需求数据区块实现年度总结的任务...

    亮剑.NET深入体验与实战精要2

    本书既考虑到实际开发中经常遇到的困惑和难题,也分析了解决问题的思路和方法,更总结出项目开发中不可或缺的技术点及思想。读者可以在欣赏一个个有趣例子的过程中,不知不觉具备开发真正商业项目的能力。 本书集...

    亮剑.NET深入体验与实战精要3

    本书既考虑到实际开发中经常遇到的困惑和难题,也分析了解决问题的思路和方法,更总结出项目开发中不可或缺的技术点及思想。读者可以在欣赏一个个有趣例子的过程中,不知不觉具备开发真正商业项目的能力。 本书集...

    开涛高可用高并发-亿级流量核心技术

    7.1 事务回滚 139 7.2 代码库回滚 140 7.3 部署版本回滚 141 7.4 数据版本回滚 142 7.5 静态资源版本回滚 143 8 压测与预案 145 8.1 系统压测 145 8.1.1 线下压测 146 8.1.2 线上压测 146 8.2 系统优化和容灾 147 ...

    工程硕士学位论文 基于Android+HTML5的移动Web项目高效开发探究

    1.3.3页面自适应机制,即设备自适应与浏览器自适应机制 8 1.3.4 “认我测”质检服务平台的设计和实现 8 1.4 本文的结构安排 8 第二章 多窗口类浏览器设计 11 2.1 多窗口类浏览器需求分析 11 2.1.1 Activity简介 11 ...

    高级软件架构师复习提纲

    28、MSF的基本要素——两个模型和三个准则分别是什么?团队模型和过程模型,项目管理准则、风险管理准则和就绪管理准则 29、使用平衡三要素管理项目范围时,需要考虑的三要素包括:资源/进度/功 30、构造用户体验...

    Visual C++ 2005入门经典--源代码及课后练习答案

    1.6.4 项目和解决方案 11 1.6.5 设置Visual C++ 2005的选项 23 1.6.6 创建和执行Windows应用程序 24 1.6.7 创建Windows Forms应用程序 26 1.7 小结 29 第2章 数据、变量和计算 31 2.1 C++程序结构 31 ...

    《iPhone开发实战》.(Christopher Allen).pdf

     本书全面探讨了 iphone平台的两种编程方式 ——web开发和 sdk编程。全书结合示例对这两种编程方式的基本流程、基本原理和基本原则给出了详细而通俗的讲解。在 web开发方面,分别介绍了三个 iphone web库,即 ...

Global site tag (gtag.js) - Google Analytics