TransactionProxy.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / ComIntegration / TransactionProxy.cs / 1 / TransactionProxy.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.ServiceModel.ComIntegration
{ 
    using System;
    using System.ServiceModel; 
    using System.Transactions; 
    using System.Diagnostics;
    using System.ServiceModel.Diagnostics; 
    using System.Runtime.InteropServices;
    using SR=System.ServiceModel.SR;

    class TransactionProxyBuilder : IProxyCreator 
    {
          ComProxy  comProxy = null; 
          TransactionProxy txProxy = null; 

          private TransactionProxyBuilder (TransactionProxy proxy) 
          {
                this.txProxy = proxy;
          }
          void IDisposable.Dispose () 
          {
 
          } 

          ComProxy IProxyCreator.CreateProxy (IntPtr outer, ref Guid riid) 
          {
               if ((riid != typeof (ITransactionProxy).GUID))
                   throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidCastException(SR.GetString(SR.NoInterface, riid)));
               if (outer == IntPtr.Zero) 
               {
                   // transactions require failfasts to prevent corruption 
                   DiagnosticUtility.FailFast("OuterProxy cannot be null"); 
               }
 
               if (comProxy == null)
               {
                   comProxy = ComProxy.Create  (outer, txProxy, null);
                   return comProxy; 

               } 
               else 
                   return comProxy.Clone ();
          } 

          bool IProxyCreator.SupportsErrorInfo (ref Guid riid)
          {
               if ((riid != typeof (ITransactionProxy).GUID)) 
                    return false;
               else 
                    return true; 

          } 

          bool IProxyCreator.SupportsDispatch ()
          {
               return false; 
          }
 
          bool IProxyCreator.SupportsIntrinsics () 
          {
               return false; 
          }

          public static IntPtr CreateTransactionProxyTearOff (TransactionProxy txProxy)
          { 
               IProxyCreator txProxyBuilder = new TransactionProxyBuilder (txProxy);;
               IProxyManager proxyManager = new ProxyManager  (txProxyBuilder); 
               Guid iid = typeof (ITransactionProxy).GUID; 
               return  OuterProxyWrapper.CreateOuterProxyInstance (proxyManager, ref iid);
          } 

    }

    class TransactionProxy : ITransactionProxy, 
                             IExtension
    { 
        Transaction currentTransaction; 
        VoterBallot currentVoter;
        object syncRoot; 
        Guid appid;
        Guid clsid;
        int instanceID = 0;
 
        public TransactionProxy(Guid appid, Guid clsid)
        { 
            this.syncRoot = new object(); 
            this.appid = appid;
            this.clsid = clsid; 
        }

        public Transaction CurrentTransaction
        { 
            get
            { 
                return this.currentTransaction; 
            }
        } 
        public Guid AppId
        {
            get
            { 
                return this.appid;
            } 
        } 
        public Guid Clsid
        { 
            get
            {
                return this.clsid;
            } 
        }
        public int InstanceID 
        { 
            get
            { 
                return this.instanceID;
            }
            set
            { 
                this.instanceID = value;
            } 
        } 
        public void SetTransaction(Transaction transaction)
        { 
            lock(this.syncRoot)
            {
                if (transaction == null)
                { 
                    // transactions require failfasts to prevent corruption
                    DiagnosticUtility.FailFast("Attempting to set transaction to NULL"); 
                } 

                if (this.currentTransaction == null) 
                {
                    ProxyEnlistment enlistment;
                    enlistment = new ProxyEnlistment(this, transaction);
                    transaction.EnlistVolatile(enlistment, EnlistmentOptions.None); 
                    this.currentTransaction = transaction;
                    if (this.currentVoter != null) 
                    { 
                        this.currentVoter.SetTransaction(this.currentTransaction);
                    } 
                }
                else if (this.currentTransaction != transaction)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.TransactionMismatch()); 
                }
            } 
        } 

        // IExtension 
        public void Attach(InstanceContext owner) {}
        public void Detach(InstanceContext owner) {}

        // ITransactionProxy 
        public void Commit(Guid guid)
        { 
            // transactions require failfasts to prevent corruption 
            DiagnosticUtility.FailFast("Commit not supported: BYOT only!");
        } 

        public void Abort()
        {
            if (this.currentTransaction != null) 
            {
                this.currentTransaction.Rollback(); 
            } 
        }
 
        public IDtcTransaction Promote()
        {
            EnsureTransaction();
            return TransactionInterop.GetDtcTransaction( 
                this.currentTransaction);
        } 
 
        public void CreateVoter(
            ITransactionVoterNotifyAsync2 voterNotification, 
            IntPtr voterBallot)
        {
            if (IntPtr.Zero == voterBallot)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("voterBallot"); 

            lock(this.syncRoot) 
            { 
                if (this.currentVoter != null)
                { 
                    // transactions require failfasts to prevent corruption
                    DiagnosticUtility.FailFast("Assumption: proxy only needs one voter");
                }
 
                VoterBallot voter = new VoterBallot(voterNotification, this);
                if (this.currentTransaction != null) 
                { 
                    voter.SetTransaction(this.currentTransaction);
                } 

                this.currentVoter = voter;

                IntPtr ppv = InterfaceHelper.GetInterfacePtrForObject(typeof(ITransactionVoterBallotAsync2).GUID, this.currentVoter); 

                Marshal.WriteIntPtr(voterBallot, ppv); 
            } 
        }
 
        public DtcIsolationLevel GetIsolationLevel()
        {
            DtcIsolationLevel retVal;
            switch (this.currentTransaction.IsolationLevel) 
            {
            case IsolationLevel.Serializable : 
                retVal = DtcIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE; 
                break;
            case IsolationLevel.RepeatableRead : 
                retVal = DtcIsolationLevel.ISOLATIONLEVEL_REPEATABLEREAD;
                break;
            case IsolationLevel.ReadCommitted :
                retVal = DtcIsolationLevel.ISOLATIONLEVEL_READCOMMITTED; 
                break;
            case IsolationLevel.ReadUncommitted : 
                retVal = DtcIsolationLevel.ISOLATIONLEVEL_READUNCOMMITTED; 
                break;
            default : 
                retVal = DtcIsolationLevel.ISOLATIONLEVEL_SERIALIZABLE;
                break;
            }
            return retVal; 
        }
 
        public Guid GetIdentifier () 
        {
            return this.currentTransaction.TransactionInformation.DistributedIdentifier; 
        }

        // ITransactionProxy2
        public bool IsReusable() 
        {
            return true; 
        } 

        void ClearTransaction(ProxyEnlistment enlistment) 
        {
            lock(this.syncRoot)
            {
                if (this.currentTransaction == null) 
                {
                    // transactions require failfasts to prevent corruption 
                    DiagnosticUtility.FailFast("Clearing inactive TransactionProxy"); 
                }
                if (enlistment.Transaction != this.currentTransaction) 
                {
                    // transactions require failfasts to prevent corruption
                    DiagnosticUtility.FailFast("Incorrectly working on multiple transactions");
                } 
                this.currentTransaction = null;
                this.currentVoter = null; 
            } 
        }
 
        void EnsureTransaction()
        {
            lock(this.syncRoot)
            { 
                if (this.currentTransaction == null)
                   throw DiagnosticUtility.ExceptionUtility.ThrowHelperError (new COMException (null, HR.CONTEXT_E_NOTRANSACTION)); 
 
            }
        } 

        class ProxyEnlistment : IEnlistmentNotification
        {
            TransactionProxy proxy; 
            Transaction transaction;
 
            public ProxyEnlistment(TransactionProxy proxy, 
                                   Transaction transaction)
            { 
                this.proxy = proxy;
                this.transaction = transaction;
            }
 
            public Transaction Transaction
            { 
                get { return this.transaction; } 
            }
 
            public void Prepare(PreparingEnlistment preparingEnlistment)
            {
                this.proxy.ClearTransaction(this);
                this.proxy = null; 
                preparingEnlistment.Done();
 
            } 

            public void Commit(Enlistment enlistment) 
            {
                // transactions require failfasts to prevent corruption
                DiagnosticUtility.FailFast("Should have voted read only");
            } 

            public void Rollback(Enlistment enlistment) 
            { 
                this.proxy.ClearTransaction(this);
                this.proxy = null; 
                enlistment.Done();
            }

            public void InDoubt(Enlistment enlistment) 
            {
                // transactions require failfasts to prevent corruption 
                DiagnosticUtility.FailFast("Should have voted read only"); 
            }
        } 

        class VoterBallot : ITransactionVoterBallotAsync2, IEnlistmentNotification
        {
            const int S_OK = 0; 

            ITransactionVoterNotifyAsync2 notification; 
            Transaction transaction; 
            Enlistment enlistment;
            PreparingEnlistment preparingEnlistment; 
            TransactionProxy proxy;

            public VoterBallot(ITransactionVoterNotifyAsync2 notification, TransactionProxy proxy)
            { 
                this.notification = notification;
                this.proxy = proxy; 
            } 

            public void SetTransaction(Transaction transaction) 
            {
                if (this.transaction != null)
                {
                    // transactions require failfasts to prevent corruption 
                    DiagnosticUtility.FailFast("Already have a transaction in the ballot!");
                } 
                this.transaction = transaction; 
                this.enlistment = transaction.EnlistVolatile(
                    this, 
                    EnlistmentOptions.None);
            }

 
            public void Prepare(PreparingEnlistment enlistment)
            { 
                this.preparingEnlistment = enlistment; 
                this.notification.VoteRequest();
            } 

            public void Rollback(Enlistment enlistment)
            {
                enlistment.Done(); 
                this.notification.Aborted( 0, false, 0, S_OK );
                ComPlusTxProxyTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationTxProxyTxAbortedByTM, 
                        SR.TraceCodeComIntegrationTxProxyTxAbortedByTM, proxy.AppId, proxy.Clsid, transaction.TransactionInformation.DistributedIdentifier, proxy.InstanceID); 
                Marshal.ReleaseComObject (this.notification);
                this.notification = null; 
            }

            public void Commit(Enlistment enlistment)
            { 
                enlistment.Done();
                this.notification.Committed( false, 0, S_OK ); 
                ComPlusTxProxyTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationTxProxyTxCommitted, 
                            SR.TraceCodeComIntegrationTxProxyTxCommitted, proxy.AppId, proxy.Clsid, transaction.TransactionInformation.DistributedIdentifier, proxy.InstanceID);
                Marshal.ReleaseComObject (this.notification); 
                this.notification = null;
            }

            public void InDoubt(Enlistment enlistment) 
            {
                enlistment.Done(); 
                this.notification.InDoubt(); 
                Marshal.ReleaseComObject (this.notification);
                this.notification = null; 
            }

            public void VoteRequestDone(int hr, int reason)
            { 
                if( this.preparingEnlistment == null )
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                        SR.GetString(SR.NoVoteIssued)));
                } 

                if(S_OK == hr)
                {
                    this.preparingEnlistment.Prepared(); 
                }
                else 
                { 

                    this.preparingEnlistment.ForceRollback(); 
                    ComPlusTxProxyTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationTxProxyTxAbortedByContext,
                            SR.TraceCodeComIntegrationTxProxyTxAbortedByContext, proxy.AppId, proxy.Clsid, transaction.TransactionInformation.DistributedIdentifier, proxy.InstanceID);
                }
            } 
        }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK