在上一篇文章“NET简谈事务、分布式事务处理”中我大概总结了关于.NET中的事务处理方式和结合了WCF框架的简单应用。在事务性操作中我们的重点是能将数据进行可逆化,说白了就是能保证数据的ACID(关于事务的整体模型、原理请参见“.NET简谈事务本质论”一文),在.NET事务处理框架中强大的类库帮我们实现了很多事务传递、事务自动提升的技术难点,同时也提供了很多扩展接口,只要我们肯去研究总能有收获。[王清培版权所有,转载请给出署名]
- public class IEnlistmentNotificationDemo<T, Xcopy> : IEnlistmentNotification
- where T : new()
- where Xcopy : class
- {
- T _commitfrontvalue;
- T _rollbackfrontvalue = new T();
- Xcopy copy;
- public IEnlistmentNotificationDemo(T t, Xcopy icopy)
- {
- (icopy as IResourceCopy<T>).Copy(_rollbackfrontvalue, t);
- _commitfrontvalue = t;//保持对资源修改的引用
- copy = icopy;
- }
- #region IEnlistmentNotification 成员
- public void Prepare(PreparingEnlistment preparingEnlistment)
- {
- //两阶段提交协议中的准备阶段
- Console.WriteLine("准备提交");
- ConsoleKeyInfo key = Console.ReadKey();
- if (key.KeyChar == 'Y' || key.KeyChar == 'y')
- {
- preparingEnlistment.Prepared(); //投票提交事务
- }
- else if (key.KeyChar == 'N' || key.KeyChar == 'n')
- {
- Console.WriteLine("\n由我投票整个事务回滚:" + _rollbackfrontvalue);
- (copy as IResourceCopy<T>).Copy(_commitfrontvalue, _rollbackfrontvalue);//回滚事务自愿
- preparingEnlistment.ForceRollback();//投票回滚事务,资源管理发生错误时因该将其自动回复数据,
- //因为事务管理不会通知发生ForceRollback()方法的管理器。
- }
- }
- public void Commit(Enlistment enlistment)
- {
- //尝试提交
- Console.WriteLine("事务尝试提交");
- enlistment.Done();//通知事务管理器,参与者已完成提交工作。
- }
- public void Rollback(Enlistment enlistment)
- {
- //事务激活阶段处理错误,执行回滚
- Console.WriteLine("操作失败,回滚" + _rollbackfrontvalue);
- (copy as IResourceCopy<T>).Copy(_commitfrontvalue, _rollbackfrontvalue);//回滚事务自愿
- enlistment.Done();
- }
- public void InDoubt(Enlistment enlistment)
- {
- //与其他的资源管理器失去联系
- Console.WriteLine("与其他的资源管理器失去联系,通常记录日志");
- enlistment.Done();
- }
- #endregion
- }
- /// <summary>
- /// 事务性资源管理器中的资源拷贝,不同的资源类型存在多种拷贝形式。
- /// </summary>
- public interface IResourceCopy<T>
- {
- void Copy(T t1, T t2);
- }
- /// <summary>
- /// StringBuilder类型的数据Copy对象,需要实现IResourceCopy泛型接口。
- /// </summary>
- public class StringBuilderCopy : IResourceCopy<StringBuilder>
- {
- #region IResourceCopy<StringBuilder> 成员
- public void Copy(StringBuilder t1, StringBuilder t2)
- {
- t1.Remove(0, t1.Length);
- t1.Append(t2.ToString());
- }
- #endregion
- }
代码4:将自定义的资源管理器参与到事务处理中
- /// <summary>
- /// 事务范围内的登记资源管理对象的状态
- /// </summary>
- public class EnlistmentDemo
- {
- [MethodImpl(MethodImplOptions.Synchronized)]//锁住当前方法,避免多线程访问破坏事务资源的一致性。
- public void Start()
- {
- //易失性资源
- StringBuilder stringvalues = new StringBuilder("123");
- StringBuilder stringvalues2 = new StringBuilder("456");
- StringBuilder stringvalues3 = new StringBuilder("789");
- StringBuilder stringvalues4 = new StringBuilder("101112");
- //使用资源管理器进行管理
- IEnlistmentNotificationDemo<StringBuilder, StringBuilderCopy> resource =
- new IEnlistmentNotificationDemo<StringBuilder, StringBuilderCopy>(stringvalues, new StringBuilderCopy());
- IEnlistmentNotificationDemo<StringBuilder, StringBuilderCopy> resource2 =
- new IEnlistmentNotificationDemo<StringBuilder, StringBuilderCopy>(stringvalues2, new StringBuilderCopy());
- IEnlistmentNotificationDemo<StringBuilder, StringBuilderCopy> resource3 =
- new IEnlistmentNotificationDemo<StringBuilder, StringBuilderCopy>(stringvalues3, new StringBuilderCopy());
- IEnlistmentNotificationDemo<StringBuilder, StringBuilderCopy> resource4 =
- new IEnlistmentNotificationDemo<StringBuilder, StringBuilderCopy>(stringvalues4, new StringBuilderCopy());
- try
- {
- using (TransactionScope transcope = new TransactionScope())
- {
- Transaction.Current.TransactionCompleted += new TransactionCompletedEventHandler(commitran_TransactionCompleted);
- //登记事务资源管理器,在开始一切事务性操作之前必须先登记资源管理器
- Transaction.Current.EnlistVolatile(resource, EnlistmentOptions.None);
- Transaction.Current.EnlistVolatile(resource2, EnlistmentOptions.None);
- Transaction.Current.EnlistVolatile(resource3, EnlistmentOptions.None);
- Transaction.Current.EnlistVolatile(resource4, EnlistmentOptions.None);
- //开始事务性操作,该阶段属于事务的激活阶段。
- stringvalues.Append("456");
- stringvalues2.Append("789");
- stringvalues3.Append("101112");
- stringvalues4.Append("131415");
- transcope.Complete();//开始两阶段提交,该阶段属于事务的准备阶段。
- }
- }
- catch { Console.WriteLine("事务执行出错,执行回滚"); }
- //查看被事务性操作后的值
- Console.WriteLine("事务完成后的结果值:");
- Console.WriteLine(stringvalues + "|" + stringvalues2 + "|" + stringvalues3 + "|" + stringvalues4);
- }
- //事务结束时触发的事件方法,可以捕获事务执行结果。
- void commitran_TransactionCompleted(object sender, TransactionEventArgs e)
- {
- Console.WriteLine("transaction completed:");
- Console.WriteLine("ID: {0}", e.Transaction.TransactionInformation.LocalIdentifier);
- Console.WriteLine("Distributed ID: {0}", e.Transaction.TransactionInformation.DistributedIdentifier);
- Console.WriteLine("Status: {0}", e.Transaction.TransactionInformation.Status);
- Console.WriteLine("IsolationLevel: {0}", e.Transaction.IsolationLevel);
- }
- }
图1:COMMIT事务
图2:ROLLBACK事务
这样我们就能很好的将自定义的资源管理器参与到事务处理当中来,对于分布式的事务处理其实也是一样的,在事务的操作范围内首先进行资源管理器的登记才能使用。[王清培版权所有,转载请给出署名]