5 // Atsushi Enomoto <atsushi@ximian.com>
6 // Ankit Jain <JAnkit@novell.com>
13 using DTCOption = System.Transactions.EnterpriseServicesInteropOption;
15 namespace System.Transactions
17 public sealed class TransactionScope : IDisposable
19 static TransactionOptions defaultOptions =
20 new TransactionOptions (0, TransactionManager.DefaultTimeout);
22 Transaction transaction;
23 Transaction oldTransaction;
24 TransactionScope parentScope;
27 /* Num of non-disposed nested scopes */
34 public TransactionScope ()
35 : this (TransactionScopeOption.Required,
36 TransactionManager.DefaultTimeout)
40 public TransactionScope (Transaction transaction)
41 : this (transaction, TransactionManager.DefaultTimeout)
45 public TransactionScope (Transaction transaction,
47 : this (transaction, timeout, DTCOption.None)
51 [MonoTODO ("EnterpriseServicesInteropOption not supported.")]
52 public TransactionScope (Transaction transaction,
53 TimeSpan timeout, DTCOption opt)
55 Initialize (TransactionScopeOption.Required,
56 transaction, defaultOptions, opt, timeout);
59 public TransactionScope (TransactionScopeOption option)
60 : this (option, TransactionManager.DefaultTimeout)
64 public TransactionScope (TransactionScopeOption option,
67 Initialize (option, null, defaultOptions,
68 DTCOption.None, timeout);
71 public TransactionScope (TransactionScopeOption scopeOption,
72 TransactionOptions options)
73 : this (scopeOption, options, DTCOption.None)
77 [MonoTODO ("EnterpriseServicesInteropOption not supported")]
78 public TransactionScope (TransactionScopeOption scopeOption,
79 TransactionOptions options,
82 Initialize (scopeOption, null, options, opt,
83 TransactionManager.DefaultTimeout);
86 void Initialize (TransactionScopeOption scopeOption,
87 Transaction tx, TransactionOptions options,
88 DTCOption interop, TimeSpan timeout)
94 if (timeout < TimeSpan.Zero)
95 throw new ArgumentOutOfRangeException ("timeout");
97 this.timeout = timeout;
99 oldTransaction = Transaction.CurrentInternal;
101 Transaction.CurrentInternal = transaction = InitTransaction (tx, scopeOption);
102 if (transaction != null)
103 transaction.InitScope (this);
104 if (parentScope != null)
105 parentScope.nested ++;
108 Transaction InitTransaction (Transaction tx, TransactionScopeOption scopeOption)
113 if (scopeOption == TransactionScopeOption.Suppress) {
114 if (Transaction.CurrentInternal != null)
115 parentScope = Transaction.CurrentInternal.Scope;
119 if (scopeOption == TransactionScopeOption.Required) {
120 if (Transaction.CurrentInternal == null) {
122 return new Transaction ();
125 parentScope = Transaction.CurrentInternal.Scope;
126 return Transaction.CurrentInternal;
130 if (Transaction.CurrentInternal != null)
131 parentScope = Transaction.CurrentInternal.Scope;
133 return new Transaction ();
136 public void Complete ()
139 throw new InvalidOperationException ("The current TransactionScope is already complete. You should dispose the TransactionScope.");
144 internal bool IsComplete {
145 get { return completed; }
148 internal TimeSpan Timeout
150 get { return timeout; }
153 public void Dispose ()
160 if (parentScope != null)
161 parentScope.nested --;
164 transaction.Rollback ();
165 throw new InvalidOperationException ("TransactionScope nested incorrectly");
168 if (Transaction.CurrentInternal != transaction) {
169 if (transaction != null)
170 transaction.Rollback ();
171 if (Transaction.CurrentInternal != null)
172 Transaction.CurrentInternal.Rollback ();
174 throw new InvalidOperationException ("Transaction.Current has changed inside of the TransactionScope");
177 if (Transaction.CurrentInternal == oldTransaction && oldTransaction != null)
178 oldTransaction.Scope = parentScope;
180 Transaction.CurrentInternal = oldTransaction;
182 if (transaction == null)
183 /* scope was not in a transaction, (Suppress) */
186 transaction.Scope = null;
189 transaction.Rollback ();
194 /* Non-root scope has completed+ended */
197 transaction.CommitInternal ();