5 // Atsushi Enomoto <atsushi@ximian.com>
6 // Ankit Jain <JAnkit@novell.com>
14 using DTCOption = System.Transactions.EnterpriseServicesInteropOption;
16 namespace System.Transactions
18 public sealed class TransactionScope : IDisposable
20 static TransactionOptions defaultOptions =
21 new TransactionOptions (0, TransactionManager.DefaultTimeout);
23 Transaction transaction;
24 Transaction oldTransaction;
25 TransactionScope parentScope;
28 /* Num of non-disposed nested scopes */
35 public TransactionScope ()
36 : this (TransactionScopeOption.Required,
37 TransactionManager.DefaultTimeout)
41 public TransactionScope (Transaction transaction)
42 : this (transaction, TransactionManager.DefaultTimeout)
46 public TransactionScope (Transaction transaction,
48 : this (transaction, timeout, DTCOption.None)
52 [MonoTODO ("EnterpriseServicesInteropOption not supported.")]
53 public TransactionScope (Transaction transaction,
54 TimeSpan timeout, DTCOption opt)
56 Initialize (TransactionScopeOption.Required,
57 transaction, defaultOptions, opt, timeout);
60 public TransactionScope (TransactionScopeOption option)
61 : this (option, TransactionManager.DefaultTimeout)
65 public TransactionScope (TransactionScopeOption option,
68 Initialize (option, null, defaultOptions,
69 DTCOption.None, timeout);
72 public TransactionScope (TransactionScopeOption scopeOption,
73 TransactionOptions options)
74 : this (scopeOption, options, DTCOption.None)
78 [MonoTODO ("EnterpriseServicesInteropOption not supported")]
79 public TransactionScope (TransactionScopeOption scopeOption,
80 TransactionOptions options,
83 Initialize (scopeOption, null, options, opt,
84 TransactionManager.DefaultTimeout);
87 void Initialize (TransactionScopeOption scopeOption,
88 Transaction tx, TransactionOptions options,
89 DTCOption interop, TimeSpan timeout)
95 if (timeout < TimeSpan.Zero)
96 throw new ArgumentOutOfRangeException ("timeout");
98 this.timeout = timeout;
100 oldTransaction = Transaction.CurrentInternal;
102 Transaction.CurrentInternal = transaction = InitTransaction (tx, scopeOption);
103 if (transaction != null)
104 transaction.InitScope (this);
105 if (parentScope != null)
106 parentScope.nested ++;
109 Transaction InitTransaction (Transaction tx, TransactionScopeOption scopeOption)
114 if (scopeOption == TransactionScopeOption.Suppress) {
115 if (Transaction.CurrentInternal != null)
116 parentScope = Transaction.CurrentInternal.Scope;
120 if (scopeOption == TransactionScopeOption.Required) {
121 if (Transaction.CurrentInternal == null) {
123 return new Transaction ();
126 parentScope = Transaction.CurrentInternal.Scope;
127 return Transaction.CurrentInternal;
131 if (Transaction.CurrentInternal != null)
132 parentScope = Transaction.CurrentInternal.Scope;
134 return new Transaction ();
137 public void Complete ()
140 throw new InvalidOperationException ("The current TransactionScope is already complete. You should dispose the TransactionScope.");
145 internal bool IsComplete {
146 get { return completed; }
149 internal TimeSpan Timeout
151 get { return timeout; }
154 public void Dispose ()
161 if (parentScope != null)
162 parentScope.nested --;
165 transaction.Rollback ();
166 throw new InvalidOperationException ("TransactionScope nested incorrectly");
169 if (Transaction.CurrentInternal != transaction) {
170 if (transaction != null)
171 transaction.Rollback ();
172 if (Transaction.CurrentInternal != null)
173 Transaction.CurrentInternal.Rollback ();
175 throw new InvalidOperationException ("Transaction.Current has changed inside of the TransactionScope");
178 if (Transaction.CurrentInternal == oldTransaction && oldTransaction != null)
179 oldTransaction.Scope = parentScope;
181 Transaction.CurrentInternal = oldTransaction;
183 if (transaction == null)
184 /* scope was not in a transaction, (Suppress) */
187 transaction.Scope = null;
190 transaction.Rollback ();
195 /* Non-root scope has completed+ended */
198 transaction.CommitInternal ();