体系结构:SQL事务处理、ADO.NET事务处理、COM+事务处理
数据库事务处理:T-SQL语句中完成, Begin Transaction Commit/Roll Back
BEGIN TRANSACTION:
BEGIN TRANSACTION { tran_name} {trans_name1| @tran_name-veriable1}事务名不得超过32个字符,否则自截断。此处变量的类型仅可以是char、varchar、nchar、nvarchar 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+中的组件需要REQUIRED或SUPPORTED。当组件需要同活动中其他事务处理的提交或回滚隔离开来的时候建议使用REQUIRESNEW。COM+事务有手动处理和自动处理,自动处理就是在所需要自动处理的方法前加上[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 } } |
自动事务处理示例(只需要在方法前面加上AutoComplete的attribute声明即可):
[AutoComplete] public void TestTransaction() { InsertRecord(); DeleteRecord(); UpdateRecord2(); } |
三者性能比较:
性能排名: SQL事务处理>ADO.NET事务处理>COM+事务处理
SQL事务处理只需要进行一次数据库交互,优点就是速度很快,而且所有逻辑包含在一个单独的调用中,与应用程序独立,缺点就是与数据库绑定。
ADO.NET需要2n次数据库往返,但相对而言,ADO.NET事务处理性能比SQL事务处理低很少,在一般应用程序中可以忽略。而且ADO.NET事务处理将事务处理与数据库独立,增加了程序的移植性。而且他也可以横跨多个数据库,不过他对于数据库的类型要求一致。
COM+事务处理性能最低,主要因为COM+本身的一些组件需要内存开销。但COM+可以横跨各种数据存储文件,这一点功能是前两者所无法媲美的。