浙林龙哥

   :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

原文参考:Using distributed transactions in .Net 1.x without deriving from ServicedComponent

COM+或者System.EnterpriseServices最常用的功能就是它对分布式事务的支持,并且自动事务处理模型很容易通过特性 ([Transaction] 和 [AutoComplete])来实现,这是很常用并且很好的做法,但是,你的类需要从ServicedComponent继承,并且 Transaction特性仅仅在类一级有效,同时你还需要将你的组件注册到COM+中。
如果这些看起来很复杂,但你需要的仅仅是需要使用分布式事务而已,而你并不关心其它的COM+功能,这里将为你提供一个解决方案:通过使用System.EnterpriseServices.ServiceDomain来实现对分布事务的支持。

using System;
using System.EnterpriseServices;
namespace SDSample
{
   class Class1
   {
      [MTAThread]      
      static void Main(string[] args)
      {
         ServiceConfig config = new ServiceConfig();
         config.Transaction = TransactionOption.Required;
         ServiceDomain.Enter(config);
         try
         {

            MyTxCode();
     ContextUtil.SetComplete();

         }

         catch(Exception e)

         {
            // we got an exception
            Console.WriteLine(e.Message);
            // 我们需要退出事务,对常写COM+组件的人不会陌生
            ContextUtil.SetAbort();
         }

         finally
         {
            ServiceDomain.Leave();
         }

      }

      // 我的事务代码
      static void MyTxCode()
      {
         Console.WriteLine(ContextUtil.TransactionId);
         // Open connection to database 1
         // Execute update in database 1
         // Open connection to database 2
         // Execute update in database 2
      }
   }
}

当然, 更进一步,你可以创建一个辅助类型, 我们叫它 ESTransactionScope (与Whidbey 中的 System.Transactions.TransactionScope类似) :
using System;

using System.EnterpriseServices;

 

namespace SDSample2

{

   class Class1

   {

      [MTAThread]      

      static void Main(string[] args)

      {

         using( ESTransactionScope ts = new ESTransactionScope())

         {

           MyTxCode();

 

           // Everything went well, no exception thrown

           // so let’s vote for Commit

           ts.Complete();

         }

      }

 

      static void MyTxCode()

      {

         Console.WriteLine(ContextUtil.TransactionId);

                 

         // Open connection to database 1

         // Execute update in database 1

 

         // Open connection to database 2

         // Execute update in database 2             

      }

   }

 

   // Used to create transactional code blocks

   class ESTransactionScope : IDisposable

   {

      // Dispose must be called to exit the transactional block

      public void Dispose()

      {                

         if(!this.Consistent)

         {

            ContextUtil.SetAbort();

         }

         ServiceDomain.Leave();

      }

 

      // by calling this method, you mark the scope as being consistent

      // and ready to for commit

      // if the method is never called, upon dispose, the scope will abort the transaction

      public void Complete()

      {

         this.Consistent = true;

      }  

 

      public ESTransactionScope()

      {                

         EnterTxContext(TransactionOption.Required);

      }

 

      public ESTransactionScope(TransactionOption txOption)

      {

         EnterTxContext(txOption);

      }

 

      private void EnterTxContext(TransactionOption txOption)

      {

         ServiceConfig config = new ServiceConfig();

         config.Transaction = txOption;

         ServiceDomain.Enter(config);          

      }

 

      // By default, the scope is inconsistent;

      // To Commit the transaction on exit, the Consistent flag

      // must be set to true before Dispose is called

      private bool Consistent = false;

   }

}

 注:在.NET Framework 2.0中提供一个System.Transaction的命名空间,其实现原来于上述相同,同样依赖COM+提供的DTC服务

posted on 2007-05-24 09:29  浙林龙哥  阅读(398)  评论(0编辑  收藏  举报