一、什么是TransactionScope?

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

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

      

题目内容:

二、TransactionScope有什么用?

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

style=”font-size: 16px;”> Quartz.NET快速上手第一课(官网文档翻译)

NMEA-0183协议是为了在不同的GPS(全球定位系统)导航设备中建立统一的BTCM(海事无线电技术委员会)标准,由美国国家海洋电子协会(NMEA-The
National Marine Electronics
Associa-tion)制定的一套通讯协议。GPS接收机根据NMEA-0183协议的标准规范,将位置、速度等信息通过串口传送到PC机、PDA等设备。

三、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 }

       

 

四、问题探讨

style=”font-size: 16px;”>原文链接

NMEA-0183协议是GPS接收机应当遵守的标准协议,也是目前GPS接收机上使用最广泛的协议,大多数常见的GPS接收机、GPS数据处理软件、导航软件都遵守或者至少兼容这个协议。

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、事务什么时候提交? 图片 1

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

 在你使用调度者( style=”color: #ff0000; background-color: #ffffff;”>scheduler)之前,你需要对它进行实例化(谁能猜到这呢?)。在实例化scheduler时候,你需要使用 style=”color: #ff0000;”>ISchedulerFactory。

NMEA-0183协议定义的语句非常多,但是常用的或者说兼容性最广的语句只有$GPGGA、$GPGSA、$GPGSV、$GPRMC、$GPVTG、$GPGLL等。

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

图片 2

图片 3

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

 

 

4、嵌套事务

style=”font-size: 16px;”> 在你实例化好scheduler后。你可以启动、让它处于等待模式以及关闭它。请注意: style=”color: #ff0000;”>一旦scheduler关闭后,将不能再被重启使用。除非你在实例化新的scheduler。如果scheduler没有被启动触发器不会被启动(Triggers)(Ijob实例对象中的代码也不会被执行),触发器保持为等待状态

 

其中$GPRMC语句的格式如下:

图片 4

图片 5

 

 

    $GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50

 1     // construct a scheduler factory
 2     ISchedulerFactory schedFact = new StdSchedulerFactory();
 3     
 4     // get a scheduler
 5     IScheduler sched = schedFact.GetScheduler();
 6     sched.Start();
 7     
 8     // define the job and tie it to our HelloJob class
 9    IJobDetail job = JobBuilder.Create<HelloJob>()
10         .WithIdentity("myJob", "group1")
11         .Build();
12   
13    // Trigger the job to run now, and then every 40 seconds
14    ITrigger trigger = TriggerBuilder.Create()
15       .WithIdentity("myTrigger", "group1")
16       .StartNow()
17       .WithSimpleSchedule(x => x
18           .WithIntervalInSeconds(40)
19           .RepeatForever())
20       .Build();
21       
22   sched.ScheduleJob(job, trigger);

 

style=”font-size: 16px;”>如上面代码所示,让Quartz.NET工作起来想当简单。在下一节中,我们将会给出Jobs
and Triggers的快速预览,这样你就会更清楚的理解上面这段代码。

这里整条语句是一个文本行,行中以逗号“,”隔开各个字段,每个字段的大小(长度)不一,这里的示例只是一种可能,并不能认为字段的大小就如上述例句一样。

    字段0:$GPRMC,语句ID,表明该语句为Recommended Minimum Specific
GPS/TRANSIT Data(RMC)推荐最小定位信息

    字段1:UTC时间,hhmmss.sss格式

    字段2:状态,A=定位,V=未定位

    字段3:纬度ddmm.mmmm,度分格式(前导位数不足则补0)

    字段4:纬度N(北纬)或S(南纬)

    字段5:经度dddmm.mmmm,度分格式(前导位数不足则补0)

    字段6:经度E(东经)或W(西经)

发表评论

电子邮件地址不会被公开。 必填项已用*标注