zoukankan      html  css  js  c++  java
  • .Net中实现事务的几种方法总结

    <!--[if !supportLists]-->.Net中实现事务的几种方法总结:

    1.   <!--[endif]-->通过后台数据库的SQL语句实现事务,在后台数据库端通过语句来实现转帐业务,如下:

    Set xact_abort on

    Begin tran

    Update A_user set balance = balance -10000 where uid=’211705’

    Update B_user set balance = balance + 10000 where uid=’462509’

    Commit tran

    其中Set xact_abort on 很重要,要没有的话,数据库就不会自动回滚出现错误的事务。

    也可以手动实现回滚事务,代码如下:

    Declare @a_userError int,

    Declare @b_userError int

    Begin tran

    Update A_user set balance = balance -10000 where uid=’211705’

    Set @a_userError = @@Error

    Update B_user set balance = balance + 10000 where uid=’462509’

    Set @b_userError = @@Error

    If @a_userError=0 and @b_userError=0 then

    Begin

    Commit tran

    Return (1) -- return 1 meaning is Trans commit successful

    End

    Else

    Begin

    Rollback tran

    Return (0) – return 0 meaning is Trans commit failed

    End

    手动回滚的语句多一些,但是有返回值,以便在程序中判断是否执行成功。

    <!--[if !supportLists]-->2.   <!--[endif]-->通过ADO.NET组件实现事务:

    通过***Transaction实现事务,是在数据库连接上创建事务处理对象,然后调用事务处理对象来提交或回滚事务,前面转账的例子:

    SqlConnection conn = new SqlConnection(“”);

    Conn.Open();

    SqlTransaction tran = Conn.BeginTransaction();

    SqlCommand cmd = new SqlCommand();

    cmd.connection = Conn;

    cmd.Transaction = tran;

    try

    {

    cmd.CommandText = “Update A_user set balance = balance -10000 where uid=’211705’”;

             cmd.ExecuteNonQuery();

    cmd.CommandText = “Update B_user set balance = balance + 10000 where uid=’462509’”;

             cmd.ExecuteNonQuery();

              tran.Commit();

    }

    Catch(Exception ex)

    {

               Tran.Rollback();

    }

    这种方式实现的事务提交的代码结构很清晰,但是在硬编码事务的情况下,任何修改业务逻辑或用户需求的改变都需要重新修改并编译源代码。

    <!--[if !supportLists]-->3.   <!--[endif]-->通过COM+提供的事务支持实现事务处理:

    .NET中要访问COM+提供的事务支持,首先必须把.NET程序集注册到COM+组件容器中,要把.NET程序集注册到COM+中必须满足以下条件:

    a. 程序集必须使用强名称签名

    b. 程序集内包含的类必须从ServicedComponent类继承

    c. 程序集必须添加到特定的COM+应用程序中

    d. 程序集必须在Windows注册表中注册

    <!--[if !supportLists]-->1)         <!--[endif]-->首先在.NET命令中使用sn.exe工具生成强名称,如sn –k test.snk,将生成的密钥文件拷到程序目录下,然后在assemblyinfo.cs修改assemblykeyfile路径,如

    [assembly:assemblykeyFile(“..\\test.snk”)]

    <!--[if !supportLists]-->2)         <!--[endif]-->ServicedComponent类继承,要从该类继承必须先引入System.EnterpriseService.dll类库。

    <!--[if !supportLists]-->3)         <!--[endif]-->声明程序集加入COM+应用程序名称,如:[assembly:applicationName(“testComplus”)]

    这行代码必须添加到类文件中,而且在using指令后类代码定义之前。

    这样就可以在类代码中通过ContextUtil类来调用COM+提供的上下文环境来实现事务处理了,如下代码:

    Using system.EnterpriseServices;

    Using System.Data.SqlClient;

    //声明当前组件添加到COM+中名为testComplus应用程序内。

    [assembly:applicationName(“testComplus”)]

    Namespace complusAppDemo

    {

           //使用transaction属性声明当前组件需要COM+提供事务支持

           [Transaction(TransactionOption.Required)]

    Public class TransactionDemo:ServicedComponent

           {

                  Public TransactionDemo(){}

                  Public bool TransDemo()

    {

                          SqlConnection conn = new SqlConnection(“”);

    Conn.Open();

    SqlCommand cmd = new SqlCommand();

        cmd.connection = Conn;

    try

    {

    cmd.CommandText = “Update A_user set balance = balance -10000 where uid=’211705’”;

                                cmd.ExecuteNonQuery();

    cmd.CommandText = “Update B_user set balance = balance + 10000 where uid=’462509’”;

                                cmd.ExecuteNonQuery();

                                 ContextUtil.SetComplete(); //调用COM+上下文提交数据

                                 Return true;

    }

    Catch(Exception ex)

    {

                                  ContextUtil.SetAbout(); //调用COM+上下文回滚事务

                                  Return false;

    }

    }

           }

    }

    代码与使用ADO.NET实现事务处理的代码很相似,但是他们执行的原理不同,ADO.NETSqlTransaction类实现事务时调用后台数据库的事务处理引擎,而COM+事务调用的COM+支持的DTC(Distributed Transaction Coordinator分布式事务协同器)服务来实现。

    将项目编译为complusAppDemo.dll后,用regsvcs.exe工具首先把complusAppDemo.dll组件的类型信息写入系统注册表,然后再根据[assembly:applicationName(“testComplus”)]创建一个COM+应用程序,并将组件添加到该应用程序中。这样就可以在应用程序中调用TransactionDemo类的TransDemo()方法来实现事务处理。

    <!--[if !supportLists]-->4.   <!--[endif]-->使用.NET的事务组件,System.Transactions命名空间下的TransactionScope对象。

    using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required))

    {

    dal.Insert(order);

        // Update the inventory to reflect the current inventory after the order submission

         Inventory inventory = new Inventory();

         inventory.TakeStock(order.LineItems);

         // Calling Complete commits the transaction.

         // Excluding this call by the end of TransactionScope's scope will rollback the transaction

         ts.Complete();

    }

    <!--[if !supportLists]-->5.   <!--[endif]-->分布式事务处理

    前面说的都是基于单个数据库实现的事务处理,但若要处理的两条或多天业务位于不同的地方的数据库时,就要跨数据库实现事务处理,这就需要使用分布式事务处理技术。在.NET框架编程中,我们可以通过两种不同的方式实现分布式事务处理:基于数据库的链接服务器和基于COM+来实现。

    <!--[if !supportLists]-->a.        <!--[endif]-->基于链接服务器实现分布式事务处理:

    首先我们需要构建链接服务器,参考SQL Server联机帮助,构建好链接服务器后在SQL Server管理器中就可以看到远程服务器了。然后就可以编写如下SQL语句实现分布式事务了:

    SET XACT_ABORT_ON

    Begin distributed tran

    Update A_user set balance = balance -10000 where uid=’211705’

    Update BCENTER.northwind.dbo.B_user set balance = balance + 10000 where uid=’462509’

    Commit tran

    与单台数据库服务器事务处理不一样的地方是第2行和第4行,其中第2行声明当前事务处理为分布式事务处理,第4行声明对BCENTER服务器上的northwind数据库的B_user数据表操作。

    所以这种实现分布式的方式在编码上比较简单,但是配置和部署的工作量增加了,因为我们首先需要建立链接服务器。

    <!--[if !supportLists]-->b.        <!--[endif]-->基于COM+实现

    通过COM+实现分布式事务处理与实现单个数据库的事务处理都是通过DTC来实现的,但是分布式事务处理在原理上与单台服务器是有差异的。COM+实现分布式事务处理时,需要DTC的事务处理引擎与不同数据库的事务管理器通讯,发送需要执行的事务操作,数据库的事务管理器在执行该操作后将结果返回到DTC,如果所有的事务管理器返回的都是正确信息,则DTC发出提交指令到各个数据库事务管理器,数据修改提交的后台数据库,分布式事务完成。如果有任何一个数据库事务管理器返回错误信息,则DTC发出回滚指令,分布式事务撤销。这就是两阶段提交的分布式事务操作。

    代码与实现单个数据库的事务处理很相似,只需在两个不同的数据库连接上执行这两个command命令。

    比较上述两种不同的分布式事务处理方式,我们可以看出使用链接服务器实现分布式事务时部署起来比较麻烦,而使用COM+实现则部署方便,但是链接服务器实现的分布式事务可以封装为存储过程,将来修改业务逻辑升级应用程序比较方便,而通过COM+实现时一旦业务规则改变就需要重新修改和编译代码。

  • 相关阅读:
    JavaScript初探 三 (学习js数组)
    JavaScript初探 二 (了解数据)
    JavaScript初探 一(认识JavaScript)
    2019暑假学习督促安排
    【C#】让工具栏ToolStrip能触发焦点控件的Leave、Validating、DataError等事件以验证数据
    【C#】回调方法不通过object参数获得委托实例
    【SQL】找出行数与自增标识值不相等的表(即有缺行)
    【SQL】统计所有表的行数
    【SQL】靠谱的TRIM函数,附赠过程一枚
    【C#】在窗体中水平居中的控件,到了XP下不居中的解决办法
  • 原文地址:https://www.cnblogs.com/colder/p/1712271.html
Copyright © 2011-2022 走看看