探索逻辑事务 TransactionScope

一、什么是TransactionScope?

  TransactionScope即范围事务(类似数据库中的事务),保证事务声明范围内的一切数据修改操作状态一致性,要么全部成功,要么全部失败回滚.

  MSDN:如果在事务范围内未不发生任何异常 (即之间的初始化 TransactionScope 对象并调用其 Dispose 方法),则范围所参与的事务可以继续,否则参与到其中的事务将回滚。
      当应用程序完成所有工作时它想要在事务中执行,应调用 Complete 方法一次,以通知该事务管理器是可接受(此时事务并未提交),即可提交事务,未能调用此方法中止事务。
      调用 Dispose 方法将标记事务范围的末尾。 在调用此方法之后所发生的异常不会影响事务。

二、TransactionScope有什么用?

  假如现在有一个需求:实现一个下单功能,主要业务包含扣减商品库存、扣减用户账户余额、生成订单记录以及记录日志。为了保证数据一致性我们通常的做法就是在数据库建一个下订单的事务,然后程序调用事务传入相应的参数即可。那么问题来了,如果用户的账户数据跟订单数据分别处于不同的数据库,就没法在同一个数据库事务里完成所有任务,也就没法保证数据的一致性。
  最近由于业务的变更公司改用MySQL数据库,处理数据变更时习惯性先写事务,写的时候发现现有数据库中一个事务都没有,于是去问java组,不使用事务怎么保证数据的一致性?得到的答复是:事务是什么鬼,spring帮我们解决所有问题...。立马就懵逼了,.net中没听说有Spring啊(据说有类似的框架),虽然可以考虑使用仓储加工作单元来解决,但是感觉好麻烦的样子,后来寻找解决方案时发现了TransactionScope。

三、TransactionScope怎么使用?

 1 try
 2 {
 3     using (TransactionScope scope = new TransactionScope())
 4     {
 5         //TODO:数据处理业务
 6         scope.Complete();
 7     }
 8 }
 9 catch (Exception ex)
10 {
11     throw ex;
12 }

四、问题探讨

1、准备工作

 1 //数据库访问对象
 2 public class Studuent
 3 {
 4     public static IList<StudentModel> GetList()
 5     {
 6         //不允许脏读
 7         string sql = "SELECT Id,Name,CreateTime FROM Student ORDER BY Id DESC;";
 8         DataTable dt = SQLHelper.ExecuteDataTable(CommandType.Text, sql);
 9         return dt.ToModel<StudentModel>();
10     }
11
12     public static bool Add(string name)
13     {
14         SqlParameter[] parms = { new SqlParameter("@Name", SqlDbType.NVarChar, 32) { Value = name } };
15         string sql = "INSERT INTO Student (Name) VALUES (@Name)";
16         return SQLHelper.ExecuteNonQuery(CommandType.Text, sql, parms) > 0;
17     }
18
19     public static void Clear()
20     {
21         SQLHelper.ExecuteNonQuery("DELETE Student");
22     }
23 }
 1 //公共方法,输出学生列表
 2 static void PrintStudent()
 3 {
 4     IList<StudentModel> list = Studuent.GetList();
 5     foreach (var item in list)
 6     {
 7         Console.WriteLine("{0}\t{1}\t{2}", Thread.CurrentThread.ManagedThreadId, item.Name, item.CreateTime);
 8     }
 9     Console.WriteLine();
10 }

2、事务什么时候提交?

最初我以为在执行Complete后即刻提交,但根据输出结果可以看出,Complete方法执行两秒之后事务依旧没有提交。因为不允许脏读的原因,主线程会在事务对Student表操作完成后才可查询完成,但学生列表是在scope调用dispose方法之后输出,MSDN介绍说dispose确定事务范围末尾,因此猜测事务是在调用dispose时被提交。

3、异常是怎么导致数据不被提交?

对比两幅图可以看出,异常在Complete之后发生并不会影响事务的提交,事务未提交是因为发生异常导致Complete未被执行。之前看过一篇文章说,如果TransactionScope范围中没有调用Complete会导致程序异常,我想他肯定是开玩笑的...

4、嵌套事务

时间: 2024-10-25 23:20:45

探索逻辑事务 TransactionScope的相关文章

C#轻量级企业事务 - TransactionScope

1 using System; 2 using System.Data.SqlClient; 3 using System.Transactions; 4 5 namespace SomeDBTransaction 6 { 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 string con1 = "SERVER=.; DATABASE=db1; UID=sa; PWD=llh"; 12 string con2

C#中的事务TransactionScope

TransactionOptions transactionOption = new TransactionOptions(); //设置事务隔离级别 transactionOption.IsolationLevel = System.Transactions.IsolationLevel.Serializable; // 设置事务超时时间为60秒 transactionOption.Timeout = new TimeSpan(0, 0, 30); using (TransactionScop

分布式事务TransactionScope所导致几个坑

记录一下,个人见解,欢迎指正 错误: 1.该伙伴事务管理器已经禁止了它对远程/网络事务的支持. (异常来自 HRESULT:0x8004D025)2.事务已被隐式或显式提交,或已终止3.此操作对该事务的状态无效. 通过分析得到这个是与分布式事务有关的问题..有以下解决办法: 1.设置 数据库的链接字符串属性:  Enlist=false    类似于:Data Source="*;Initial Catalog=*;User ID=sa;Password=sa;Enlist=false;&quo

EntityFrameWork使用TransactionScope分布式事务,存储区更新、插入或删除语句影响到了意外的行数(0)。实体在加载后可能被修改或删除。刷新 ObjectStateManager 项 错误

最近在开发一个小型的物业管理系统,系统其中有一个功能需要每个月按抄的水表.电表等生成相应的费用,数据库主要的基础数据表有大楼水.电表.楼层水.电表.房间水电表:其中大楼和楼层的水电表是用于计算公摊的:系统设计有一个费用的统计表,表名ChargeAccountMaster,表内设计的有一个字段ID,主键 . 自增长:计算时由于是数据核算统计,所以引入事务计算数据的同时,也会把相应计算的结果回写回基础数据表中,计算的类是service层,框架的ORM用的是EF,就没有采用本地事务,采用了分布式事务T

谈谈分布式事务之三: System.Transactions事务详解[下篇]

在前面一篇给出的Transaction的定义中,信息的读者应该看到了一个叫做DepedentClone的方法.该方法对用于创建基于现有Transaction对 象的“依赖事务(DependentTransaction)”.不像可提交事务是一个独立的事务对象,依赖事务依附于现有的某个事务(可能是可提交事 务,也可能是依赖事务).依赖事务可以帮助我们很容易地编写一些事务型操作,当环境事务不存的时候,可以确保操作在一个独立的事务中执行:当环境事务存在 的时候,则自动加入其中. 一.依赖事务(Depen

DataBase 之 存储过程、函数、触发器、事务、游标

(1)存储过程 [1]创建存储过程(无参) create procedure ProTestAas  select * from TestA --修改存储过程(有参,且为输出参数)alter procedure ProTestA@LastName varchar(10) = null outputas  if @LastName is null  begin     print 'null'     print '123'  end  else  begin  print @LastName 

net中的4种事务总结

在一个MIS系统中,没有用事务那就绝对是有问题的,要么就只有一种情况:你的系统实在是太小了,业务业务逻辑有只要一步执行就可以完成了.因此掌握事务处理的方法是很重要,进我的归类在.net中大致有以下4种事务处理的方法.大家可以参考一下,根据实际选择适当的事务处理.1 SQL事务    sql事务是使用SQL server自身的事务:在存储过程中直接使用Begin Tran,Rollback Tran,Commit Tran实现事务:优点:执行效率最佳限制:事务上下文仅在数据库中调用,难以实现复杂的

[转]Spring3核心技术之事务管理机制

原文地址:http://chouyi.iteye.com/blog/1675199 Spring对事务的解决办法其实分为2种:编程式实现事务,AOP配置声明式解决方案. http://jinnianshilongnian.iteye.com/blog/1496953 Spring提供了许多内置事务管理器实现,常用的有以下几种: DataSourceTransactionManager:位于org.springframework.jdbc.datasource包中,数据源事务管理器,提供对单个ja

事务的特征、隔离级别以及事务的传播

事务 一组具有明确边界的,并且是有一定顺序的执行过程.是企业开发过程中必不可少的一门技术.通常用来确保一组执行过程的完整性与一致性. 例如:张三给李四转钱,这就是一个完整的过程,任何一部出问题,事务都是不完整的. 事务的四大特征:原子性(Atomicity):事务是一个完整的过程,不可以再次划分.具有原子的特征. 一致性(Consistency):一旦事务进行,无论有多少个事务,处理事务的过程中,数据总是满足质量守恒定律.入多少---出多少. 隔离性(Isolation):事务与事务执行过程中,