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;
27 /* 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)
92 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 public void Dispose ()
153 if (parentScope != null)
154 parentScope.nested --;
157 transaction.Rollback ();
158 throw new InvalidOperationException ("TransactionScope nested incorrectly");
161 if (Transaction.CurrentInternal != transaction) {
162 if (transaction != null)
163 transaction.Rollback ();
164 if (Transaction.CurrentInternal != null)
165 Transaction.CurrentInternal.Rollback ();
167 throw new InvalidOperationException ("Transaction.Current has changed inside of the TransactionScope");
170 if (Transaction.CurrentInternal == oldTransaction && oldTransaction != null)
171 oldTransaction.Scope = parentScope;
173 Transaction.CurrentInternal = oldTransaction;
175 if (transaction == null)
176 /* scope was not in a transaction, (Suppress) */
179 transaction.Scope = null;
182 transaction.Rollback ();
187 /* Non-root scope has completed+ended */
190 transaction.CommitInternal ();