zoukankan      html  css  js  c++  java
  • .NET三种事务处理详解

    体系结构:SQL事务处理、ADO.NET事务处理、COM+事务处理

    数据库事务处理:T-SQL语句中完成, Begin Transaction Commit/Roll Back

    BEGIN TRANSACTION

    BEGIN TRANSACTION { tran_name}

    {trans_name1| @tran_name-veriable1}事务名不得超过32个字符,否则自截断。此处变量的类型仅可以是charvarcharncharnvarchar

    WITH MARK ['DESCRIPTION'] 指定在日志中标记事务

    EXPRESSION2

    BEGIN TRANS启动一个本地事务,但是在应用程序执行一个必须的记录操作之前,他不被记录在事务日志中。

    With Mark选项使得事务名被置于事务日志中,将数据还原到早期状态时,可使用标记事务代替日期和时间。

    在未标记的数据库事务中可以嵌套标记的事务。如

    BEGIN TRAN T1

    UPDATE table1 ...

    BEGIN TRAN M2 WITH MARK

    UPDATE table2 ...

    SELECT * from table1

    COMMIT TRAN M2

    UPDATE table3 ...

    COMMIT TRAN T1

    命名事务示例:

    DECLARE @TranName VARCHAR(20)

    SELECT @TranName = 'MyTransaction'

    BEGIN TRANSACTION @TranName

    USE AdventureWorks

    DELETE FROM AdventureWorks.HumanResources.JobCandidate

    WHERE JobCandidateID = 13

    COMMIT TRANSACTION @TranName

    标记事务示例:

    BEGIN TRANSACTION CandidateDelete

    WITH MARK N'Deleting a Job Candidate'

    USE AdventureWorks

    DELETE FROM AdventureWorks.HumanResources.JobCandidate

    WHERE JobCandidateID = 13

    COMMIT TRANSACTION CandidateDelete

    COMMIT TRANSACTION

    COMMIT {TRAN|TRANSACTION}

    [transaction_name | [@tran_name_variable ] ]BEGIN部分的规则

    [ ; ]

    提交一般事务示例:

    USE AdventureWorks

    BEGIN TRANSACTION

    DELETE FROM HumanResources.JobCandidate

    WHERE JobCandidateID = 13

    COMMIT TRANSACTION

    提交嵌套事务示例:

    BEGIN TRANSACTION OuterTran

        INSERT INTO TestTran VALUES (1, 'aaa')

        BEGIN TRANSACTION Inner1

            INSERT INTO TestTran VALUES (2, 'bbb')

            BEGIN TRANSACTION Inner2

                INSERT INTO TestTran VALUES (3, 'ccc')

            COMMIT TRANSACTION Inner2

        COMMIT TRANSACTION Inner1

    COMMIT TRANSACTION OuterTran

    ROLLBACK TRANSACTION

    ROLLBACK { TRAN | TRANSACTION }

    --transaction_name同上,此处savepoint_name规则同transaction_name,为SAVE TRANSACTION 语句中的savepoint_name,用于条件回滚之影响事务的一部分

    [ transaction_name | @tran_name_variable | savepoint_name | @savepoint_variable ]

    [ ; ]

    示例:

    USE TempDB

    CREATE TABLE ValueTable ([value] int)

    BEGIN TRAN Transaction1

    INSERT INTO ValueTable VALUES(1)

    INSERT INTO ValueTable VALUES(2)

    SELECT * FROM ValueTable

    ROLLBACK TRAN Transaction1

    SELECT * FROM ValueTable

    INSERT INTO ValueTable VALUES(3)

    INSERT INTO ValueTable VALUES(4)

    SELECT * FROM ValueTable

    DROP TABLE ValueTable

    结果:

    综合示例:

    begin TRAN

        declare @orderDetailsError int,@procuntError int

      delete from [order details] where productid=42

      select @orderDetailsError =@@error

      delete from products where productid=42

      select @procuntError=@@error

      if(@orderDetailsError =0 and @procuntError=0)

           COMMIT TRAN

      else

           ROLLBACK TRAN

    ADO.NET事务处理:

    示例:

    public void ExecuteNoneSql(string p_sqlstr, params string[] p_cmdStr)

    {

    using (SqlConnection conn = new SqlConnection(p_sqlstr))

    {

    Conn.Open();

    SqlCommand cmd = new SqlCommand();

    cmd.Connection = conn;

    SqlTransaction trans = null;

    trans = conn.BeginTransaction(); //初始化事务

    cmd.Transaction = trans; //绑定事务

    try

    {

    for (int i = 0; i < p_cmdStr.Length; i++)

    {

    cmd.CommandText = p_cmdStr[i];

    cmd.CommandType = CommandType.Text;

    cmd.ExecuteNonQuery();

    }

    trans.Commit(); //提交

    }

    catch (SqlException e)

    {

    if (trans != null) trans.Rollback(); //回滚

    else

    {//写日志}

    }

    }

    }

    带保存点回滚示例:

    using (SqlConnection conn = new SqlConnection(p_sqlstr))

    {

    conn.Open();

    SqlCommand cmd = new SqlCommand();

    cmd.Connection = conn;

    SqlTransaction trans = conn.BeginTransaction("table");

    cmd.Transaction = trans;

    try

    {

    cmd.CommandText = "Insert into table_name1 values(values1,values2,....)";

    cmd.CommandType = CommandType.Text;

    cmd.ExecuteNonQuery();

    cmd.CommandText = "Insert into table_name2 values(values1,values2,....)";

    cmd.CommandType = CommandType.Text;

    cmd.ExecuteNonQuery();

    trans.Save("table1");

    cmd.CommandText = "Insert into table_name2 values(values1,values2,....)";

    cmd.CommandType = CommandType.Text;

    cmd.ExecuteNonQuery();

    trans.Save("table2");

    trans.Commit();

    }

    catch

    {

    try

    { trans.Rollback("table2") ; }

    catch

    {

    try{ trans.Rollback("table1") ; }

    catch{ trans.Rollback("table") ; }

    }

    }

    }

    COM+事务处理:

    COM+事务必须继承自System.EnterpriseServices.ServicedComponent其实WEB也是继承自该类,所以WEB支持COM+事务处理。

    第一步、新建一个COM+事务处理的类。

    [Transaction(TransactionOption.Required)]

    public class MyCOMPlus : System.EnterpriseServices.ServicedComponent

    {

    ..............

    }

    TransactionOption为枚举类型,具有五个选项。

    DISABLED忽略当前上下文中的任何事务

    NOTSUPPORTED使用非受控事件创建组件

    REQUIRED如有事务存在则共享事务,如有必要则创建事务(事务池,事务处理中所选择项)REQUIRESNEW是有新建的事务,与上下文无关

    SUPPORTED如果事务存在则共享事务。

    一般来说COM+中的组件需要REQUIREDSUPPORTED。当组件需要同活动中其他事务处理的提交或回滚隔离开来的时候建议使用REQUIRESNEWCOM+事务有手动处理和自动处理,自动处理就是在所需要自动处理的方法前加上[AutoComplete],根据方法的正常或抛出异常决定提交或回滚。手动处理其实就是调用EnableCommit()SetComplete()SetAbort()方法。

    手动处理示例:

    public void TestTransaction()

    {

    try

    {

    ContextUtil.EnableCommit(); //对应BEGIN TRANSACTION

    InsertRecord();

    DeleteRecord();

    UpdateRecord2();

    ContextUtil.SetComplete(); //对应TRANSACTION.COMMIT

    }

    catch (Exception ex)

    {

    ContextUtil.SetAbort(); //对应TRANSACTION.ROLLBACK

    }

    }

    自动事务处理示例(只需要在方法前面加上AutoCompleteattribute声明即可):

    [AutoComplete]

    public void TestTransaction()

    {

    InsertRecord();

    DeleteRecord();

    UpdateRecord2();

    }

    三者性能比较:

    性能排名: SQL事务处理>ADO.NET事务处理>COM+事务处理

    SQL事务处理只需要进行一次数据库交互,优点就是速度很快,而且所有逻辑包含在一个单独的调用中,与应用程序独立,缺点就是与数据库绑定。

    ADO.NET需要2n次数据库往返,但相对而言,ADO.NET事务处理性能比SQL事务处理低很少,在一般应用程序中可以忽略。而且ADO.NET事务处理将事务处理与数据库独立,增加了程序的移植性。而且他也可以横跨多个数据库,不过他对于数据库的类型要求一致。

    COM+事务处理性能最低,主要因为COM+本身的一些组件需要内存开销。但COM+可以横跨各种数据存储文件,这一点功能是前两者所无法媲美的。

  • 相关阅读:
    JavaScript词法结构
    【python】类变量、实例变量
    把pandas dataframe转为list方法
    list 删除一个元素的三种做法--python
    Web.config中rewite 节点引起的500.19错误
    extjs让按钮可用或者不可用
    VS2010启动奔溃
    迟来的年终总结
    Nginx配置多个server
    RestSharp的简单用法
  • 原文地址:https://www.cnblogs.com/chenbg2001/p/2016321.html
Copyright © 2011-2022 走看看