c#传统SqlTransaction事务和TransactionScope事务
事务有很多种,看了一些关于事务的问题,这里做下笔记·····
事务时单个的工作单位。如果某一事务成功,则在该事务中进行的所有数据更改均会提交,成为数据库中永久的组成部分。若果事务遇到错误,则必须取消或回滚,所有数据均被更改清除。
属性:
1.原子性:事务是一个完整的操作,事务的各元素师不可分的。
2.一致性:事务开始时和完成时,数据必须处于一致的状态。
3.隔离性:对数据进行修改的所有并发事务是彼此隔离的。
4.持久性:事务完成后,它对系统的影响是永久的。
1.连接相关SqlTransaction事务
Transact-SQL使用下列语句来管理事务:
开始事务:BEGIN TRANSACTION
提交事务:COMMIT TRANSACTION
回滚:ROLLBACK TRANSACTION
private static void ExecuteSqlTransaction(string connstr) { using (SqlConnection conn = new SqlConnection(connstr)) { conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { SqlTransaction transaction = conn.BeginTransaction("SampleTransaction"); //开始事务 cmd.Connection = conn; cmd.Transaction = transaction; try { cmd.CommandText = "Insert into Department (ID, Name) VALUES (2, '开发部')"; cmd.ExecuteNonQuery(); cmd.CommandText = "Insert into Users(ID, Name,DepartmentID) VALUES (2, 'sxw',2)"; cmd.ExecuteNonQuery(); transaction.Commit(); //事务完成之后提交事务 } catch (Exception ex) { transaction.Rollback(); //如果事务没有完成,就回滚事务 } } } }
注意:在提交或回滚 SqlTransaction 时,应始终使用 Try/Catch 进行异常处理。如果连接终止或事务已在服务器上回滚,则Commit 和Rollback 都会生成InvalidOperationException
虽然SqlTransaction事务应用很广泛,但SqlTransaction事务也有自己的缺点,就是不能实现分布式事务、嵌套事务、编写也麻烦。下面介绍能实现分布式事务的方法,编程相对来说还是很方便的
2.TransactionScope实现分布式事务
想在编程中使用TransactionScope实现分布式事务,
首先要在电脑服务中启动MSDTC(Distributed Transaction Coordinator)服务····
(注意:MSDTC服务只要把数据交互的电脑上的此服务打开就可以,如果是客户端直接访问服务器,则客户端和服务器的MSDTC服务都要打开,
如果客户端只是与中间层交互,中间层才与服务器数据交互,则客户端的MSDTC服务可以不用打开,但中间层和服务器的MSDTC服务必须启动。
在第一次启动MSDTC服务时,服务的启动类型都是手动启动,这是可以把启动类型改成自动启动,这样下次就不需要自己手动启动了)
其次需要在项目中添加对System.Transactions的引用
最后就可以在代码中引用TransactionScope的Complete方法。进行事务操作。
//使用事务保证原子性 using (TransactionScope ts = new TransactionScope()) { SqlHelp.ExecuteNonQuery("Insert into Department (ID, Name) VALUES (@Id, '开发部')", new SqlParameter("@Id", Id)); SqlHelp.ExecuteNonQuery("Insert into Users(ID, Name,DepartmentID) VALUES (@Id, 'sxw',2)", new SqlParameter("@Id", Id)); ts.Complete(); //完成事务,这个必须加上,要不然事务不会有效 }
TransactionScope也可以实现嵌套式事务,也就是A调用B,B中声明了TransactionScope事务,A中也声明了,这样如果B没错,但是A调完B后出错,则B中的数据库操作也回滚。