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 [MonoTODO ("No TimeoutException is thrown")]
66 public TransactionScope (TransactionScopeOption option,
69 Initialize (option, null, defaultOptions,
70 DTCOption.None, timeout);
73 public TransactionScope (TransactionScopeOption scopeOption,
74 TransactionOptions options)
75 : this (scopeOption, options, DTCOption.None)
79 [MonoTODO ("EnterpriseServicesInteropOption not supported")]
80 public TransactionScope (TransactionScopeOption scopeOption,
81 TransactionOptions options,
84 Initialize (scopeOption, null, options, opt,
85 TransactionManager.DefaultTimeout);
88 void Initialize (TransactionScopeOption scopeOption,
89 Transaction tx, TransactionOptions options,
90 DTCOption interop, TimeSpan timeout)
95 this.timeout = timeout;
97 oldTransaction = Transaction.CurrentInternal;
99 Transaction.CurrentInternal = transaction = InitTransaction (tx, scopeOption);
100 if (transaction != null)
101 transaction.InitScope (this);
102 if (parentScope != null)
103 parentScope.nested ++;
106 Transaction InitTransaction (Transaction tx, TransactionScopeOption scopeOption)
111 if (scopeOption == TransactionScopeOption.Suppress) {
112 if (Transaction.CurrentInternal != null)
113 parentScope = Transaction.CurrentInternal.Scope;
117 if (scopeOption == TransactionScopeOption.Required) {
118 if (Transaction.CurrentInternal == null) {
120 return new Transaction ();
123 parentScope = Transaction.CurrentInternal.Scope;
124 return Transaction.CurrentInternal;
128 if (Transaction.CurrentInternal != null)
129 parentScope = Transaction.CurrentInternal.Scope;
131 return new Transaction ();
134 public void Complete ()
137 throw new InvalidOperationException ("The current TransactionScope is already complete. You should dispose the TransactionScope.");
142 internal bool IsComplete {
143 get { return completed; }
146 internal TimeSpan Timeout
148 get { return timeout; }
151 public void Dispose ()
158 if (parentScope != null)
159 parentScope.nested --;
162 transaction.Rollback ();
163 throw new InvalidOperationException ("TransactionScope nested incorrectly");
166 if (Transaction.CurrentInternal != transaction) {
167 if (transaction != null)
168 transaction.Rollback ();
169 if (Transaction.CurrentInternal != null)
170 Transaction.CurrentInternal.Rollback ();
172 throw new InvalidOperationException ("Transaction.Current has changed inside of the TransactionScope");
175 if (Transaction.CurrentInternal == oldTransaction && oldTransaction != null)
176 oldTransaction.Scope = parentScope;
178 Transaction.CurrentInternal = oldTransaction;
180 if (transaction == null)
181 /* scope was not in a transaction, (Suppress) */
184 transaction.Scope = null;
187 transaction.Rollback ();
192 /* Non-root scope has completed+ended */
195 transaction.CommitInternal ();