如何让普通变量也支持事务回滚?
有一次和人谈起关于事务的话题,谈到怎样的资源才能事务型资源。除了我们经常使用的数据库、消息队列、事务型文件系统(TxF)以及事务性注册表(TxR)等,还有那些资源直接可以纳入事务进行状态的管理呢?我说如果我们按照.NET事务模型的规范对相应的资源进行合理的封装,原则上我们可以让任何可编程的资源成为事务型资源。本篇文章中,我将通过简单的编程将一个普通的变量变成支持事务,让变量的值也可以回滚,以确保事务前后的数据一致性。 一、什么是事务型的变量本文中所说的事务型变量指的是这样的变量:
上面的对事务型变量的描述可以通过下面的程序来体现:变量v在初始化时被赋值为1。然后通过TransactionScope开始一个事务,并将变量纳入该事务之中。在事务范围内将值赋值为2,然后调用DoSomething方法,并提交事务。如果DoSomething执行过程中抛出异常,整个事务将会回滚。当整个事务中止回滚后,变量v的值回复到事务开始之前的状态,即值为1。 1: static void Main(string[] args) 3: TransactionalVariable<int> v = new TransactionalVariable<int>(1); 5: { 7: { 9: v.Value = 2; 11: transactionScope.Complete(); 13: } 15: { } 17: } 二、简单谈谈System.Transactions事务模型事务型变量的性质已经说得很清楚了,现在根本的任务就是如何来定义这样的一个事务性变量类型,即上面实例程序中的TransactionalVariable<T>类型。不过在这之前,我们有必要简单看谈谈System.Transactions的事务模型。对于所有的事务参与者,按照各自在整个事务生命周期各个阶段所承担的职能,大致扮演着如下三种角色:
关于System.Transactions具体的事务管理模型,可以参考我的文章《谈谈分布式事务之二:基于DTC的分布式事务管理模型[上篇]》,在这里就不在赘言介绍了。总而言之,只要我们能够为变量编写相应的“资源管理器”,我们就能够将其纳入到System.Transactions.Transaction之中。在System.Transactions体系中,编写事务管理器是一件很简单的事情,一种非常直接的方式就是实现IPromotableSinglePhaseNotification这么一个接口。实例代码中使用的TransactionalVariable<T>类型就是这么定义的。 三、通过实现IPromotableSinglePhaseNotification接口定义TransactionalVariable<T>在具体介绍TransactionalVariable<T>的定义之前,我们不妨来看看IPromotableSinglePhaseNotification接口是如何定义的。下面的代码片断反映了IPromotableSinglePhaseNotification的定义:加上从父接口继承下来的成员,整个IPromotableSinglePhaseNotification接口一共具有4个方法成员。Initialize方法会在资源纳入事务的时候被调用,用于执行一些初始化操作。SinglePhaseCommit、Rollback和Promote用于通知事务正在被提交、回滚和提升。 2: { void Rollback(SinglePhaseEnlistment singlePhaseEnlistment); 6: } 8: { 10: } TransactionalVariable<T>直接实现了IPromotableSinglePhaseNotification接口,下面是全部的定义。TransactionalVariable<T>中定义了两个数据成员,字段_originalValue和属性Value代表变量的初始值和当前值。
2: namespace Artech.TransactionalObjects
class TransactionalVariable<T> : IPromotableSinglePhaseNotification 7: public T Value { get; set; }
9:? 11: { 13: } 15: void Initialize()
17: _originalValue = this.Value;
19:? 21: { 23: singlePhaseEnlistment.Aborted(); 25:? 27: { 29: singlePhaseEnlistment.Committed(); 31:? 33: { 35: } 37: } 以上就是所有的实现,并没有什么特别之处,仅仅就是通过实现对初始值的缓存,进而实现在事务中止时能够将值恢复到之前的状态。你可以通过这里下载该例子。不过,这个例子仅仅是一个简单的模拟演示而已,还有很多不足之处。比如事务四大属性的隔离性在TransactionalVariable<T>就不能体现出来。
作者:Artech
出处:http://artech.cnblogs.com 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-mvc – 将一个类对象从一个控制器动作传递到ASP.ne
- asp.net-mvc – 我有15分钟向我的同事介绍ASP.NET MVC 我应
- asp.net-mvc-3 – 是否可以嵌套部分视图?
- 使用Asp.net Web API时,使用DataContract和DataMember属性有
- asp.net-mvc-3 – Paypal Sandbox MVC3
- asp.net-mvc – 在ASP.NET MVC中下载动态生成的文件
- asp.net – System.Net.Cookie和System.Web.HttpCookie有什
- asp.net – IIS 7强制新鲜图像
- asp.net – 如何在经典的asp中使用.net共享会话?
- 在ASP.NET/IIS的URL中使用冒号(:)