.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+可以横跨各种数据存储文件,这一点功能是前两者所无法媲美的。

原文地址:https://www.cnblogs.com/chenbg2001/p/2016321.html