.net 基础类库.实列.System.Transactions.自定义事物 (对2.0 加的事物类进行讲解)

.net 基础类库.实列.System.Transactions.自定义事物 (对新正加的事物类进行讲解)

涉及技术
自定义事物类,以及 System.Transactions 下的一些类库的使用
线程级别静态变量(这个子要在变量上加个 [ThreadStatic] 就可高定)
文件io访问(这个就不讲解了太没意识了MSDN说的很清楚)


 上篇文章 “状态机工作流.实列.报销审批流程(三) ” 发表之后发现IPendingWork 接口会传入一个 System.Transactions.Transaction 对象于是产生了兴趣研究了2个小时
写了一个小程序和大家分享一下成果 2006-10-09 23:28


   可能很多人已经知道很多数据库操作对象都已经支持 “事物性代码”如果不知道去看看 TransactionScope 类的msdn的帮助去,难道只有数据库对象会自动支持这种事物吗?
那当然是不可能的,不过作者找了半天也没有发现那个类的帮助上写了会支持“事物性代码”、子找到如下字样
   System.Transactions
基础结构通过支持在 SQL Server、ADO.NET、MSMQ 和 Microsoft 分布式事务协调器 (MSDTC) 中启动的事务,使事务编程在整个平台上变得简单和高效、看来没别的对象了。

  自己能做一个吗?答案是肯定的,继续搜寻MSDN 发现一个 IEnlistmentNotification 接口子要实现他,在用 Transaction.Current.EnlistVolatile 登记一下就应该好使了, MSDN上有一个简单的列子在 IEnlistmentNotification 接口的下面,不过那个列子太简单了几乎是简单到啥用都没有的地步了

  还是自己给自己搞个需求吧要不没法做的!
需求如下

  1. 要做一个多文件读写删除,保存如果失败就回滚的例子
  2. 在多个函数里写不同的文件最后回滚
  3. 适合在ASP.net那种多线程访问的情况下使用没有问题

哎文件 io里的那些流都不支持 这个郁闷还真得好好设计一下,怎么自持多个文件的回滚那当然是放到列表里的了!怎么在多个函数里都可以使用哪?只能提供一个单列的对象了看来
,不过存静态的单列有线程问题,不能用哎!.
对了用那个 [ThreadStatic] 标签,这个标签我用了好久很爽尤其在Web那种多线程可能并发的情况下...
可以了啥都不缺了开始做吧

[程序下载 / download],是一个命令行程序演示没图

类设计/使用方法说明
  1. transFileModel


         ///   <summary>
        
    ///  文件路经模块类,用于保存一些路径信息
        
    ///   </summary>
         internal   class  transFileModel
        {
            
    // 备份文件目录
             public   string  BakFileDir  =   string .Empty;
            
    // 文件全路径
             public   string  FileAllPath  =   string .Empty;
            
    // 备份全路径
             public   string  BakGuidAllPath  =   string .Empty;

        }

  2. ContextData

      
    ///   <summary>
        
    ///  对象保存类,保存要进行事物处理的文件路经
        
    ///   </summary>
         internal   class  ContextData
        {
            
    public   static   object  _olock  =   new   object ();
            
    ///   <summary>
            
    ///  文件路径模块列表
            
    ///   </summary>
             public  List < transFileModel >  FileList  =   new  List < transFileModel > ();

            
    static  ContextData()
            {

            }

            
    ///   <summary>
            
    ///  注意:线程级别静态变量,否则这个类会有线程冲突
            
    ///   </summary>
            [ThreadStatic]
            
    public   static  ContextData staticData  =   new  ContextData();
            
    ///   <summary>
            
    ///  文件路径模块列表对应的属性
            
    ///   </summary>
             public   static  List < transFileModel >  BakList
            {
                
    get
                {
                    
    return  staticData.FileList;
                }
            }
            
    ///   <summary>
            
    ///  添加一个 文件到 BakList
            
    ///   </summary>
            
    ///   <param name="bakDir"></param>
            
    ///   <param name="filePath"></param>
             public   static   void  AddFile( string  bakDir,  string  filePath)
            {

                bakDir 
    =  Path.GetFullPath(bakDir);
                filePath 
    =  Path.GetFullPath(filePath);

                
    lock  (_olock)
                {
    // 安全起见还是 lock 一下
                     if  ( ! Directory.Exists(bakDir))
                        Directory.CreateDirectory(bakDir);
                }

                
    string  GuidFileName  =   string .Empty;
                
    string  bakGuidAllPath  =   string .Empty;

                
    if  (File.Exists(filePath))
                {
    // 文件如果存在就备份到备份目录,并已Guid.bak方式存储
                    GuidFileName  =  Guid.NewGuid().ToString()  +   " .bak " ;
                    bakGuidAllPath 
    =  Path.Combine(bakDir, GuidFileName);

                    File.Copy(filePath, bakGuidAllPath, 
    true );

                    Console.WriteLine(
    " 文件以成功copy " );
                }

                transFileModel model 
    =   new  transFileModel();
                model.BakFileDir 
    =  bakDir;
                model.BakGuidAllPath 
    =  bakGuidAllPath;
                model.FileAllPath 
    =  filePath;

                staticData.FileList.Add(model);

            }

            
    public   static   void  ClearFileList()
            {
                BakList.Clear();
            }

        }


  3. TransactionTools


         public   class  TransactionTools : System.Transactions.IEnlistmentNotification
        {
        
            
    #region  IEnlistmentNotification 成员
            
            
    public   static   object  _olock  =   new   object ();
            
            
    public  TransactionTools()
            {
                
    if  (Transaction.Current ==   null  )  throw   new  ApplicationException( " 靠!没开事物那 " );
                Transaction.Current.EnlistVolatile(
    this ,EnlistmentOptions.None);            
            }
            
            
    ~ TransactionTools()
            {
                
            }

            
    public   static   void  RegFile( string  BakDir, string  filePath)
            {
                ContextData.AddFile(BakDir,filePath);
            }
            
            
    public   void  Commit(System.Transactions.Enlistment enlistment)
            {
                Console.WriteLine(
    " 通知登记的对象事务正在提交。: " );    
                ContextData.ClearFileList();
                enlistment.Done();
                
            }

            
    public   void  InDoubt(System.Transactions.Enlistment enlistment)
            {
                Console.WriteLine(
    " 通知登记的对象事务的状态不确定。: " );    
                
    throw   new  Exception( " The method or operation is not implemented. " );
            }

            
    public   void  Prepare(System.Transactions.PreparingEnlistment preparingEnlistment)
            {
                
    // throw new Exception("The method or operation is not implemented.");
                
    // 在这里应该判断,原始文件是否可写,备份文件是否可读
                Console.WriteLine( " 通知登记的对象事务正在为提交做准备。: " );    
                preparingEnlistment.Prepared();
            }

            
    public   void  Rollback(System.Transactions.Enlistment enlistment)
            {
                Console.WriteLine(
    " 通知登记的对象事务正在回滚。: " );    
                List
    < transFileModel >  transLsit  =  ContextData.BakList;
                
    if (transLsit.Count  >   0 )
                {
                    
                    
    foreach (transFileModel mod  in  transLsit)
                    {
                        
                        
    if (mod.BakGuidAllPath.Length  ==   0   &&  File.Exists(mod.FileAllPath))
                        {
    // 文件是新建立的,而且存在的话删除
                            Console.WriteLine( " 正在回滚删除文件: " , mod.FileAllPath);
                            File.Delete(mod.FileAllPath);
                        }
                        
    else   if (mod.BakGuidAllPath.Length  !=   0 )
                        {
    // 文件有bak路径证明,他不是新建了的需要回滚
                            Console.WriteLine( " 正在会滚文件: " , mod.FileAllPath);    
                            File.Copy(mod.BakGuidAllPath,mod.FileAllPath,
    true );
                            File.Delete(mod.BakGuidAllPath);
                        }
                        
                    }
                }

                ContextData.ClearFileList();
                enlistment.Done();
            }

            
    #endregion
            
        }
  4. 使用演示
    static   class  Program
        {
            
    static   readonly   string  BakPath  =  Path.Combine(Application.StartupPath,  " Bak " );
            
            
    // 测试函数一
             static   void  writerFile1()
            {
                
    string  fpath  =  Path.Combine(Application.StartupPath,  " a.txt " );
                TransactionTools.RegFile(BakPath, fpath);

                
    using  (StreamWriter sw  =   new  StreamWriter(fpath,  true ))
                {
                    Console.WriteLine(
    " 正写入:{0} " , fpath);
                    
                    sw.WriteLine(
    " A:{0:yyyy-MM-dd HH:mm:ss.ffff} " ,DateTime.Now);
                    
                }
                
                
                
            }
            
            
    // 测试函数二
             static   void  writerFile2()
            {
                
    string  fpath  =  Path.Combine(Application.StartupPath,  " b.txt " );
                
                TransactionTools.RegFile(BakPath, fpath);
                    
                
    using  (StreamWriter sw  =   new  StreamWriter(fpath ,  true ))
                {
                    Console.WriteLine(
    " 正写入:{0} " ,    fpath);    
                    sw.WriteLine(
    " B:{0:yyyy-MM-dd HH:mm:ss.ffff} " , DateTime.Now);
                    
                }
                
            }
            
            
    static   void  DBUpdate1()
            {
    // 数据库操作对象支持 事物性代码,起码,sqlserver 的一系列、对象支持这里我就不写更新数据库的了,自己加上吧
            
            }
            
    ///   <summary>
            
    ///  应用程序的主入口点。
            
    ///   </summary>
            [STAThread]
            
    static   void  Main()
            {

                
                
    using (TransactionScope ts  =   new  System.Transactions.TransactionScope())
                {
                    Transaction.Current.TransactionCompleted
    += new  TransactionCompletedEventHandler(Current_TransactionCompleted);
                    TransactionTools tt 
    =   new  TransactionTools();
                        
                        
    // 调用好多个函数有数据库的和文件的
                        
                        writerFile1();
                        writerFile2();
                        DBUpdate1();
                        
                        Console.Write(
    " 输入[Y] 提交否则会滚 " );
                        
    char  c  =  ( char )Console.Read();
                        
                        
    if (c.ToString().ToUpper() == " Y " )
                            ts.Complete();
                    
                    
                    
                }
                
                Console.Read();
                
    // Application.EnableVisualStyles();
                
    // Application.SetCompatibleTextRenderingDefault(false);
                
    // Application.Run(new Form1());
            }

            
    static   void  Current_TransactionCompleted( object  sender, TransactionEventArgs e)
            {
                Console.WriteLine(
    " 事物状态:{0} "  , e.Transaction.TransactionInformation.Status);
                
    // throw new Exception("The method or operation is not implemented.");
            }
        }
最后
这个文档写的比较草、也许2.0里真得有可以支持事物的 文件读写类笔者没有发现,如果谁发现了记得通知一下啊...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值