好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

WCF服务编程读书笔记(7):事务

WCF服务编程读书笔记(7):事务

Example 7-1. Explicit transaction management

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.ServiceModel.Channels;
  using   System.Diagnostics;
  using   System.Runtime.Serialization;
  using   System.ServiceModel.Dispatcher;
  using   System.ServiceModel.Description;
  using   System.Collections.ObjectModel;
  using   System.Data;
  using   System.Data.SqlClient;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
          void   MyMethod();
    }


      class   MyService : IMyContract
    {
          public   void   MyMethod()
        {
              //  Avoid this programming model 

             string  connectionString =  ""  ;

            IDbConnection conn  =  new   SqlConnection(connectionString);
            conn.Open();

            IDbCommand comm  =  new   SqlCommand();
            comm.Connection  =  conn;

            IDbTransaction trans  = conn.BeginTransaction();  //  Enlisting 
            comm.Transaction =  trans;

              try  
            {
                  //   Interact with database here, then commit the transaction 
                 trans.Commit();
            }
              catch  
            {
                trans.Rollback();   //   Abort transaction 
             }
              finally  
            {
                conn.Close();
                comm.Dispose();
                trans.Dispose();
            }
        }
    }
} 

View Code

Example 7-2. Configuring for the Client/Service transaction mode

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Diagnostics;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod();
    }


      class   MyService : IMyContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
            Transaction transaction  =  Transaction.Current;
            Debug.Assert(transaction  !=  null  );
        }
    }
} 

View Code

Example 7-3. The BindingRequirementAttribute

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel.Description;
  using   System.ServiceModel;
  using   System.Collections.ObjectModel;
  using   System.ServiceModel.Channels;

  namespace   WCFServiceProgramming.Library
{
      class   BindingRequirementAttribute : Attribute, IServiceBehavior
    {
          public   bool  TransactionFlowEnabled {  get ;  set  ; }

          public   void   AddBindingParameters(ServiceDescription description, ServiceHostBase host, 
            Collection <ServiceEndpoint>  endpoints, BindingParameterCollection parameters)
        {           
        }

          public   void   ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase host)
        {  
        }

          public   void   Validate(ServiceDescription description, ServiceHostBase host)
        {
              if  (TransactionFlowEnabled ==  false  )
            {
                  return  ;
            }

              foreach  (ServiceEndpoint endpoint  in   description.Endpoints)
            {
                Exception exception  =  new   InvalidOperationException();

                  foreach  (OperationDescription operation  in   endpoint.Contract.Operations)
                {
                      foreach  (IOperationBehavior behavior  in   operation.Behaviors)
                    {
                          if  (behavior  is   TransactionFlowAttribute)
                        {
                            TransactionFlowAttribute attribute  = behavior  as   TransactionFlowAttribute;
                              if  (attribute.Transactions ==  TransactionFlowOption.Allowed)
                            {
                                  if  (endpoint.Binding  is   NetTcpBinding)
                                {
                                    NetTcpBinding tcpBinding  = endpoint.Binding  as   NetTcpBinding;
                                      if  (tcpBinding.TransactionFlow ==  false  )
                                    {
                                          throw   exception;
                                    }
                                      break  ;
                                }

                                  //   Similar checks for the rest of the transaction-aware bindings 

                                 throw   new   InvalidOperationException();
                            }
                        }
                    }
                }
            }
        }
    }
} 

View Code

Example 7-4. Configuring for the Client transaction mode

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Diagnostics;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Mandatory)]
          void   MyMethod();
    }

      class   MyService : IMyContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
            Transaction transaction  =  Transaction.Current;
            Debug.Assert(transaction.TransactionInformation.DistributedIdentifier  !=  Guid.Empty);

        }
    }
} 

View Code

Example 7-5. Configuring for the Service transaction mode

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Diagnostics;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
          void   MyMethod();
    }

      class   MyService : IMyContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
            Transaction transaction  =  Transaction.Current;
            Debug.Assert(transaction.TransactionInformation.DistributedIdentifier  ==  Guid.Empty);

        }
    }
} 

View Code

Example 7-6. Configuring for the None transaction mode

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Diagnostics;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
          void   MyMethod();
    }

      class   MyService : IMyContract
    {
          public   void   MyMethod()
        {
            Transaction transaction  =  Transaction.Current;
            Debug.Assert(transaction  ==  null  );

        }
    }
} 

View Code

Example 7-7. Using TransactionScope

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Diagnostics;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
          void   MyMethod();
    }

      class   MyService : IMyContract
    {
          public   void   MyMethod()
        {
              using  (TransactionScope scope =  new   TransactionScope())
            {
                  //   Perform transaction work here
                  //   No errors - commit transaction 
                 scope.Complete();
            }

        }
    }
} 

View Code

Example 7-8. TransactionScope and error handling

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Diagnostics;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
          void   MyMethod();
    }

      class   MyService : IMyContract
    {
          public   void   MyMethod()
        {
              try  
            {
                  using  (TransactionScope scope =  new   TransactionScope())
                {
                      //   Perform transaction work here
                      //   No errors - commit transaction 
                     scope.Complete();
                }
            }
              catch   (TransactionAbortedException ex)
            {
                Trace.WriteLine(ex.Message);
            }
              catch  (Exception ex)  //   Any other exception took place 
             {
                Trace.WriteLine(  "  Cannot complete transaction  "  );
                  throw   ex;
            }
        }
    }
} 

View Code

Example 7-9. Direct scope nesting

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Diagnostics;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
          void   MyMethod();
    }

      class   MyService : IMyContract
    {
          public   void   MyMethod()
        {
              using  (TransactionScope scope1 =  new   TransactionScope())
            {
                  using  (TransactionScope scope2 =  new   TransactionScope())
                {
                    scope2.Complete();
                }

                scope1.Complete();
            }
        }
    }
} 

View Code

Example 7-10. Indirect scope nesting

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Diagnostics;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
          void   MyMethod();
    }

      class   MyService : IMyContract
    {
          public   void   MyMethod()
        {
              using  (TransactionScope scope =  new   TransactionScope())
            {
                  //   Perform transaction work here 
 
                SomeMethod();
                scope.Complete();
            }
        }

          private   static   void   SomeMethod()
        {
              using  (TransactionScope scope =  new   TransactionScope())
            {
                  //   Perform transaction work here 
 
                scope.Complete();
            }
        }
    }
} 

View Code

Example 7-11. Scope nesting inside a service method

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Diagnostics;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
          void   MyMethod();
    }

      class   MyService : IMyContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
              using  (TransactionScope scope =  new   TransactionScope())
            {
                  //   Perform transaction work here 
                 scope.Complete();
            }
        }
    }
} 

View Code

Example 7-12. Using TransactionScopeOption.Required in a downstream class

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Diagnostics;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
          void   MyMethod();
    }

      class   MyService : IMyContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
            MyClass obj  =  new   MyClass();
            obj.SomeMethod();
        }
    }

      class   MyClass
    {
          public   void   SomeMethod()
        {
              using  (TransactionScope scope = 
                 new   TransactionScope(TransactionScopeOption.Required))
            {
                  //   Do some work then  
                 scope.Complete();
            }
        }
    }
} 

View Code

Example 7-13. Using TransactionScopeOption.Suppress

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Diagnostics;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
          void   MyMethod();
    }

      class   MyService : IMyContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
              try  
            {
                  //   Start of nontransactional section 

                 using  (TransactionScope scope =  new   TransactionScope(TransactionScopeOption.Suppress))
                {
                      //   Do nontransactional work here 
                 }

                  //   Restores ambient transaction here 
             }
              catch  
            { }
        }
    }
} 

View Code

Example 7-14. Using TransactionScope to call services in a single transaction(Service Side)

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Diagnostics;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Library
{
      /////////////////////////////////  // Service Side   ////////////////////////////////////  // 
 
    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod();
    }

    [ServiceContract]
      public   interface   IMyOtherContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Mandatory)]
          void   MyOtherMethod();
    }

      class   MyService : IMyContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
        }
    }

      class   MyOtherService : IMyOtherContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyOtherMethod()
        {
        }
    }
} 

View Code

Example 7-14. Using TransactionScope to call services in a single transaction(Client Side)

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   WCFServiceProgramming.Library;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Client
{
      /////////////////////////////////  / Client Side   /////////////////////////////////
      class  MyContractClient : ClientBase<IMyContract> , IMyContract
    {
          public   void   MyMethod()
        {
            Channel.MyMethod();
        }
    }

      class  MyOtherContractClient : ClientBase<IMyOtherContract> , IMyOtherContract
    {
          public   void   MyOtherMethod()
        {
            Channel.MyOtherMethod();
        }
    }

      class   Program
    {
          static   void  Main( string  [] args)
        {
              using  (TransactionScope scope =  new   TransactionScope())
            {
                MyContractClient proxy1  =  new   MyContractClient();
                proxy1.MyMethod();
                proxy1.Close();

                MyOtherContractClient proxy2  =  new   MyOtherContractClient();
                proxy2.MyOtherMethod();
                proxy2.Close();

                scope.Complete();
            }

              using  (MyContractClient proxy3 =  new   MyContractClient())
              using  (MyOtherContractClient proxy4 =  new   MyOtherContractClient())
              using  (TransactionScope scope =  new   TransactionScope())
            {
                proxy3.MyMethod();
                proxy4.MyOtherMethod();

                scope.Complete();
            }
        }
    }
} 

View Code

Example 7-15. Implementing a transactional service

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Transactions;
  using   System.Runtime.Serialization;

  namespace   WCFServiceProgramming.Library
{
    [DataContract]
      class   Param
    { }

    [ServiceContract]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod();
    }

    [ServiceBehavior(InstanceContextMode  =  InstanceContextMode.PerCall)]
      class   MyService : IMyContract, IDisposable
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod(Param stateIdentifier)
        {
            GetState(stateIdentifier);
            DoWork();
            SaveState(stateIdentifier);
        }

          void   GetState(Param stateIdentifier)
        { }

          void   DoWork()
        { }

          void   SaveState(Param stateIdentifier)
        { }

          public   void   Dispose()
        { }
    }
} 

View Code

Example 7-16. Per-session yet per-call transactional service

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Transactions;
  using   System.Runtime.Serialization;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract(SessionMode  =  SessionMode.Required)]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod();
    }

    [ServiceBehavior(InstanceContextMode  =  InstanceContextMode.PerCall)]
      class   MyService : IMyContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
        }
    }
} 

View Code

Example 7-17. Per-session transactional service

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Transactions;
  using   System.Runtime.Serialization;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract(SessionMode  =  SessionMode.Required)]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod();
    }

    [ServiceBehavior(ReleaseServiceInstanceOnTransactionComplete  =  false  )]
      class   MyService : IMyContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
        }
    }
} 

View Code

Example 7-18. State-aware, transactional per-session service

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Transactions;
  using   System.Runtime.Serialization;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract(SessionMode  =  SessionMode.Required)]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod();
    }

    [ServiceBehavior(ReleaseServiceInstanceOnTransactionComplete  =  false  )]
      class   MyService : IMyContract, IDisposable
    {
          readonly   string   _stateIdentifier;

          public   MyService()
        {
            InitializeState();
            _stateIdentifier  =  OperationContext.Current.SessionId;
            SaveState();
        }

        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
            GetState();
            Dowork();
            SaveState();
        }

          public   void   Dispose()
        {
            RemoveState();
        }

          //   Helper methods 

         private   void   InitializeState()
        {
        }

          private   void   GetState()
        {
        }

          private   void   Dowork()
        {
        }

          private   void   SaveState()
        {
        }

          private   void   RemoveState()
        {
        }
    }
} 

View Code

Example 7-19. Using volatile resource managers to achieve stateful per-session transactional service

Example 7-20. Launching concurrent transactions

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   WCFServiceProgramming.Library;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Client
{
      class  MyContractClient : ClientBase<IMyContract> , IMyContract
    {
          public   void   MyMethod()
        {
            Channel.MyMethod();
        }
    }

      class   Program
    {
          static   void  Main( string  [] args)
        {
              using  (TransactionScope scope1 =  new   TransactionScope())
            {
                MyContractClient proxy  =  new   MyContractClient();
                proxy.MyMethod();

                  using  (TransactionScope scope2 =  new   TransactionScope(TransactionScopeOption.RequiresNew))
                {
                    proxy.MyMethod();
                    scope2.Complete();
                }

                proxy.Close();
                scope1.Complete();
            }
        }
    }
} 

View Code

Example 7-21. Setting TransactionAutoComplete to false

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Transactions;
  using   System.Runtime.Serialization;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract(SessionMode  =  SessionMode.Required)]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod1();

        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod2();
    }

      class   MyService : IMyContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  , 
            TransactionAutoComplete  =  false  )]
          public   void   MyMethod1()
        {
        }

        [OperationBehavior(TransactionScopeRequired  =  true  ,
            TransactionAutoComplete  =  false  )]
          public   void   MyMethod2()
        {
        }
    }
} 

View Code

Example 7-22. Hybrid per-session service

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Transactions;
  using   System.Runtime.Serialization;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract(SessionMode  =  SessionMode.Required)]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod1();

        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod2();
    }

    [ServiceBehavior(TransactionAutoCompleteOnSessionClose  =  true  )]
      class   MyService : IMyContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  , 
            TransactionAutoComplete  =  false  )]
          public   void   MyMethod1()
        {
        }

        [OperationBehavior(TransactionScopeRequired  =  true  ,
            TransactionAutoComplete  =  false  )]
          public   void   MyMethod2()
        {
        }
    }
} 

View Code

Example 7-23. State-aware singleton(Service Side)

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Transactions;
  using   System.Runtime.Serialization;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract(SessionMode  =  SessionMode.Required)]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod();
    }

    [ServiceBehavior(InstanceContextMode  =  InstanceContextMode.Single)]
      class   MyService : IMyContract
    {
          readonly   static   string  _stateIdentifier =  typeof  (MyService).GUID.ToString();

        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
            GetState();
            Dowork();
            SaveState();
        }

          private   void   GetState()
        {
        }

          private   void   Dowork()
        {
        }

          public   void   SaveState()
        {
              //   Use _stateIdentifier to save state 
         }

          public   void   RemoveState()
        {
              //   Use _stateIdentifier to remove the state from the resource manager 
         }
    }
} 

View Code

Example 7-23. State-aware singleton(Hosting)

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   WCFServiceProgramming.Library;
  using   System.ServiceModel;
  using   System.ServiceModel.Description;

  namespace   WCFServiceProgramming.Host
{
      class   Program
    {
          static   void  Main( string  [] args)
        {
            MyService singleton  =  new   MyService();
            singleton.SaveState();

            ServiceHost host  =  new   ServiceHost(singleton);
            host.Open();

              //   Some blocking calls 
 
            host.Close();
            singleton.RemoveState();
        }
    }
} 

View Code

Example 7-24. Achieving stateful singleton transactional service (Service Side)

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Transactions;
  using   System.Runtime.Serialization;
  using   System.Diagnostics;

  namespace   WCFServiceProgramming.Library
{
      //////////////////////////////  // Service Side   /////////////////////////////////
  
    [ServiceContract(SessionMode  =  SessionMode.Required)]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod();
    }

    [ServiceBehavior(InstanceContextMode  =  InstanceContextMode.Single, 
        ReleaseServiceInstanceOnTransactionComplete  =  false  )]
      public   class   MyService : IMyContract
    {
          int  _counter =  0  ;

        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
            _counter ++ ;
            Trace.WriteLine(  "  Counter:   "  +  _counter);
        }
    }
} 

View Code

Example 7-24. Achieving stateful singleton transactional service (Client Side)

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   WCFServiceProgramming.Library;
  using   System.Transactions;

  namespace   WCFServiceProgramming.Client
{
      //////////////////////////////   Client Side   /////////////////////////////////
 
     class  MyContractClient : ClientBase<IMyContract> , IMyContract
    {
          public   void   MyMethod()
        {
            Channel.MyMethod();
        }
    }

      class   Program
    {
          static   void  Main( string  [] args)
        {
              using  (TransactionScope scope1 =  new   TransactionScope())
            {
                MyContractClient proxy  =  new   MyContractClient();
                proxy.MyMethod();
                proxy.Close();
                scope1.Complete();
            }

              using  (TransactionScope scope2 =  new   TransactionScope())
            {
                MyContractClient proxy  =  new   MyContractClient();
                proxy.MyMethod();
                proxy.Close();
                scope2.Complete();
            }

              using  (TransactionScope scope3 =  new   TransactionScope())
            {
                MyContractClient proxy  =  new   MyContractClient();
                proxy.MyMethod();
                proxy.Close();
                scope3.Complete();
            }
        }
    }
} 

View Code

Example 7-25. Configuring the callback for Service transaction

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Transactions;
  using   System.Diagnostics;

  namespace   WCFServiceProgramming.Library
{
      public   interface   IMyContractCallback
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Mandatory)]
          void   OnCallback();
    }

      class   MyClient : IMyContractCallback
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   OnCallback()
        {
            Transaction transaction  =  Transaction.Current;
            Debug.Assert(transaction.TransactionInformation.
                DistributedIdentifier  !=  Guid.Empty);
        }
    }
} 

View Code

Example 7-26. Out-of-band callbacks

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Transactions;
  using   System.Runtime.Serialization;
  using   System.Diagnostics;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract(SessionMode  =  SessionMode.Required)]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod();
    }

    [ServiceBehavior(InstanceContextMode  =  InstanceContextMode.PerCall)]
      public   class   MyService : IMyContract
    {
          static  List<IMyContractCallback> _callbacks =  new  List<IMyContractCallback> ();

          public   void   MyMethod()
        {
            IMyContractCallback callback  =  
                OperationContext.Current.GetCallbackChannel <IMyContractCallback> ();

              if  (_callbacks.Contains(callback) ==  false  )
            {
                _callbacks.Add(callback);
            }
        }

          public   static   void   CallClients()
        {
            Action <IMyContractCallback> invoke =  delegate  (IMyContractCallback callback)
            {
                  using  (TransactionScope scope =  new   TransactionScope())
                {
                    callback.OnCallback();
                    scope.Complete();
                }
            };

            _callbacks.ForEach(invoke);
        }
    }
} 

View Code

//Out-of-band callbacks:
MyService.CallClients( );

Example 7-27. Configuring for transactional callbacks(Service Side)

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   System.Transactions;
  using   System.Runtime.Serialization;
  using   System.Diagnostics;

  namespace   WCFServiceProgramming.Library
{
    [ServiceContract(CallbackContract  =  typeof  (IMyContractCallback))]
      public   interface   IMyContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   MyMethod();
    }

      public   interface   IMyContractCallback
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
          void   OnCallback();
    }

    [ServiceBehavior(InstanceContextMode  =  InstanceContextMode.PerCall, 
        ConcurrencyMode  =  ConcurrencyMode.Reentrant, 
        ReleaseServiceInstanceOnTransactionComplete  =  false  )]
      public   class   MyService : IMyContract
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   MyMethod()
        {
            Trace.WriteLine(  "  Service ID:   "  +  
                Transaction.Current.TransactionInformation.DistributedIdentifier);

            IMyContractCallback callback  =  
                OperationContext.Current.GetCallbackChannel <IMyContractCallback> ();

            callback.OnCallback();
        }
    }
} 

View Code

Example 7-27. Configuring for transactional callbacks(Client Side)

 using   System;
  using   System.Collections.Generic;
  using   System.Linq;
  using   System.Text;
  using   System.ServiceModel;
  using   WCFServiceProgramming.Library;
  using   System.Transactions;
  using   System.Diagnostics;

  namespace   WCFServiceProgramming.Client
{
      class   MyClient : IMyContractCallback
    {
        [OperationBehavior(TransactionScopeRequired  =  true  )]
          public   void   OnCallback()
        {
            Trace.WriteLine(  "  OnCallback ID:   "  + 
                Transaction.Current.TransactionInformation.DistributedIdentifier);
        }
    }

      class  MyContractClient : ClientBase<IMyContract> , IMyContract
    {
          private   InstanceContext _context;

          public   MyContractClient(InstanceContext context)
        {
              this ._context =  context;
        }
          public   void   MyMethod()
        {
            Channel.MyMethod();
        }
    }

      class   Program
    {
          static   void  Main( string  [] args)
        {
            MyClient client  =  new   MyClient();
            InstanceContext context  =  new   InstanceContext(client);
            MyContractClient proxy  =  new   MyContractClient(context);

              using  (TransactionScope scope =  new   TransactionScope())
            {
                proxy.MyMethod();

                Trace.WriteLine(  "  Client ID:   "  +  
                    Transaction.Current.TransactionInformation.DistributedIdentifier);

                scope.Complete();
            }

            proxy.Close();
        }
    }
} 

View Code

查看更多关于WCF服务编程读书笔记(7):事务的详细内容...

  阅读:39次

上一篇: Extjs4 MVC 示例

下一篇:spring mvc book very good