Clover.NET coverage report - Coverage

Coverage timestamp: Friday, May 20, 2005 9:17:00 PM

File Stats: LOC: 360   Methods: 14
NCLOC: 199 Classes: 1
 
Source File Conditionals Statements Methods TOTAL
Transaction\TransactionScope.cs 0.0 % 0.0 % 0.0 % 0.0 %
coverage
1  
2   #region Apache Notice
3   /*****************************************************************************
4   * $Header: $
5   * $Revision: $
6   * $Date: $
7   *
8   * iBATIS.NET Data Mapper
9   * Copyright (C) 2004 - Gilles Bayon
10   *
11   *
12   * Licensed under the Apache License, Version 2.0 (the "License");
13   * you may not use this file except in compliance with the License.
14   * You may obtain a copy of the License at
15   *
16   * http://www.apache.org/licenses/LICENSE-2.0
17   *
18   * Unless required by applicable law or agreed to in writing, software
19   * distributed under the License is distributed on an "AS IS" BASIS,
20   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21   * See the License for the specific language governing permissions and
22   * limitations under the License.
23   *
24   ********************************************************************************/
25   #endregion
26  
27   #region Imports
28   using System;
29   using System.EnterpriseServices;
30   using System.Runtime.Remoting.Messaging;
31  
32   using log4net;
33   #endregion
34  
35   namespace IBatisNet.Common.Transaction
36   {
37   /// <summary>
38   /// Simple interface to COM+ transactions through Enterprise Service.
39   /// Makes a code block transactional à la Indigo (evolution will be easier, it's the same API)
40   /// It's important to make sure that each instance
41   /// of this class gets Close()'d.
42   /// Easiest way to do that is with the using statement in C#.
43   /// </summary>
44   /// <remarks>
45   /// Don't support nested transaction scope with different transaction options.
46   ///
47   /// System.EnterpriseServices.ServiceDomain is available only on
48   /// - XP SP2 (or higher)
49   /// - Windows Server 2003
50   /// - XP SP1 + Hotfix 828741
51   /// and only in .Net 1.1.
52   /// It CAN'T be used on Windows 2000.
53   ///
54   /// http://support.microsoft.com/default.aspx/kb/319177/EN-US/
55   /// </remarks>
56   /// <example>
57   /// using (TransactionScope tx = new TransactionScope())
58   /// {
59   ///
60   /// // Open connection to database 1
61   /// // Transaction will be automatically enlist into it
62   /// // Execute update in database 1
63   /// // Open connection to database 2
64   /// // Transaction will be automatically enlist into it
65   /// // Execute update in database 2
66   ///
67   /// // the following code will be executed only if no exception
68   /// // occured in the above code; since we got here ok, let's vote for commit;
69   /// tx.Completed();
70   /// }
71   /// when “using” call Dispose on the transaction scope at the end
72   /// of the “using” code block, the "ambient" transaction will be commited only and only if
73   /// the Completed method have been called.
74   /// </example>
75   public class TransactionScope : IDisposable
76   {
77   #region Consts
78   private const string TX_SCOPE_COUNT = "_TX_SCOPE_COUNT_";
79   private bool _consistent = false;
80   #endregion
81  
82   #region Fields
83   private bool _closed = false;
84   private TransactionScopeOptions _txScopeOptions;
85   private TransactionOptions _txOptions;
86   private static readonly ILog _logger = LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType );
87   #endregion
88  
89   #region Properties
90  
91  
92   /// <summary>
93   /// Changes the vote to commit (true) or to abort (false).
94   /// If all the TransactionScope instances involved in a
95   /// transaction have voted to commit, then the entire thing is committed.
96   /// If any TransactionScope instances involved in a
97   /// transaction vote to abort, then the entire thing is aborted.
98   /// </summary>
99 0 private bool Consistent
100   {
101   set
102   {
103   _consistent = value;
104   }
105   }
106  
107   /// <summary>
108   /// Count of the TransactionScope that have been open.
109   /// </summary>
110 0 public int TransactionScopeCount
111   {
112   get
113   {
114   object count = CallContext.GetData(TX_SCOPE_COUNT);
115   return (count == null) ? 0 : (int)count;
116   }
117   set
118   {
119   CallContext.SetData(TX_SCOPE_COUNT, value);
120   }
121   }
122  
123   /// <summary>
124   /// Returns whether or not the current thread is in a transaction context.
125   /// </summary>
126 0 public static bool IsInTransaction
127   {
128   get
129   {
130   return ContextUtil.IsInTransaction;
131   }
132   }
133  
134  
135   /// <summary>
136   /// Gets the current value of the vote.
137   /// </summary>
138 0 public bool IsVoteCommit
139   {
140   get
141   {
142   return ContextUtil.MyTransactionVote == TransactionVote.Commit;
143   }
144   }
145   #endregion
146  
147   #region Constructor (s) / Destructor
148   /// <summary>
149   /// Creates a new instance with a TransactionScopeOptions.Required
150   /// and TransactionOptions.IsolationLevel.ReadCommitted.
151   /// </summary>
152 0 public TransactionScope()
153   {
154   _txOptions = new TransactionOptions();
155   _txOptions.IsolationLevel = IsolationLevel.ReadCommitted;
156   _txOptions.TimeOut = new TimeSpan(0,0,0,15);
157  
158   _txScopeOptions = TransactionScopeOptions.Required;
159  
160   EnterTransactionContext();
161   }
162  
163  
164  
165   /// <summary>
166   /// Creates a new instance with the specified TransactionScopeOptions
167   /// and TransactionOptions.IsolationLevel.ReadCommitted.
168   /// </summary>
169   /// <param name="txScopeOptions">The specified TransactionScopeOptions</param>
170 0 public TransactionScope(TransactionScopeOptions txScopeOptions)
171   {
172   _txOptions = new TransactionOptions();
173   _txOptions.IsolationLevel = IsolationLevel.ReadCommitted;
174   _txOptions.TimeOut = new TimeSpan(0,0,0,15);
175  
176   _txScopeOptions = txScopeOptions;
177  
178   EnterTransactionContext();
179   }
180  
181  
182   /// <summary>
183   /// Creates a new instance.
184   /// </summary>
185   /// <param name="txScopeOptions">The specified TransactionScopeOptions.</param>
186   /// <param name="options">The specified TransactionOptions.</param>
187 0 public TransactionScope(TransactionScopeOptions txScopeOptions, TransactionOptions options)
188   {
189   _txOptions = options;
190   _txScopeOptions = txScopeOptions;
191  
192   EnterTransactionContext();
193   }
194   #endregion
195  
196   #region Methods
197  
198   /// <summary>
199   ///
200   /// </summary>
201 0 private void EnterTransactionContext()
202   {
203   if (++TransactionScopeCount == 1)
204   {
205   if (_logger.IsDebugEnabled)
206   {
207   _logger.Debug("Create a new ServiceConfig in ServiceDomain.");
208   }
209  
210   ServiceConfig config = new ServiceConfig();
211  
212   config.TrackingEnabled = true;
213   config.TrackingAppName = "iBATIS.NET";
214   config.TrackingComponentName = "TransactionScope";
215   config.TransactionDescription = "iBATIS.NET Distributed Transaction";
216   config.Transaction = TransactionScopeOptions2TransactionOption( _txScopeOptions );
217   config.TransactionTimeout = _txOptions.TimeOut.Seconds;
218   config.IsolationLevel = IsolationLevel2TransactionIsolationLevel( _txOptions.IsolationLevel );
219  
220   // every call to ServiceDomain.Enter() creates a new COM+ Context
221   //(verified by calls to ContextUtil.ContextId),
222   // and every call to ServiceDomain.Leave() terminates that context
223   ServiceDomain.Enter(config);
224   }
225  
226   _closed = false;
227  
228   if (_logger.IsDebugEnabled)
229   {
230   _logger.Debug("Open TransactionScope :"+ContextUtil.ContextId);
231   }
232   }
233  
234  
235  
236   /// <summary>
237   /// Give the correpondance of a TransactionScopeOptions (à la Indigo) object in a TransactionOption (COM+) object
238   /// </summary>
239   /// <param name="transactionScopeOptions">The TransactionScopeOptions to macth.</param>
240   /// <returns>The TransactionOption correspondance</returns>
241 0 private TransactionOption TransactionScopeOptions2TransactionOption(TransactionScopeOptions transactionScopeOptions)
242   {
243   TransactionOption transactionOption;
244  
245   switch(transactionScopeOptions)
246   {
247   case TransactionScopeOptions.Mandatory:
248   throw new NotImplementedException("Will be used in Indigo.");
249   case TransactionScopeOptions.NotSupported:
250   transactionOption = TransactionOption.NotSupported;
251   break;
252   case TransactionScopeOptions.Required:
253   transactionOption = TransactionOption.Required;
254   break;
255   case TransactionScopeOptions.RequiresNew:
256   transactionOption = TransactionOption.RequiresNew;
257   break;
258   case TransactionScopeOptions.Supported:
259   transactionOption = TransactionOption.Supported;
260   break;
261   default:
262   transactionOption = TransactionOption.Required;
263   break;
264   }
265   return transactionOption;
266   }
267  
268   /// <summary>
269   /// Give the correpondance of a TransactionIsolationLevel (à la Indigo) object in a IsolationLevel (COM+) object
270   /// </summary>
271   /// <param name="isolation">The IsolationLevel to macth.</param>
272   /// <returns>The TransactionIsolationLevel correspondance</returns>
273 0 private TransactionIsolationLevel IsolationLevel2TransactionIsolationLevel(IsolationLevel isolation)
274   {
275   TransactionIsolationLevel isolationLevel;
276  
277   switch(isolation)
278   {
279   case IsolationLevel.ReadCommitted:
280   isolationLevel = TransactionIsolationLevel.ReadCommitted;
281   break;
282   case IsolationLevel.ReadUncommitted:
283   isolationLevel = TransactionIsolationLevel.ReadUncommitted;
284   break;
285   case IsolationLevel.RepeatableRead:
286   isolationLevel = TransactionIsolationLevel.RepeatableRead;
287   break;
288   case IsolationLevel.Serializable:
289   isolationLevel = TransactionIsolationLevel.Serializable;
290   break;
291   case IsolationLevel.Unspecified:
292   throw new NotImplementedException("Will be used in Indigo.");
293   default:
294   isolationLevel = TransactionIsolationLevel.ReadCommitted;
295   break;
296   }
297   return isolationLevel;
298   }
299  
300   /// <summary>
301   /// Close the TransactionScope
302   /// </summary>
303 0 public void Close()
304   {
305   if (_closed == false)
306   {
307   if (_logger.IsDebugEnabled)
308   {
309   _logger.Debug("Close TransactionScope");
310   }
311  
312   if (ContextUtil.IsInTransaction)
313   {
314   if (_consistent==true && (this.IsVoteCommit))
315   {
316   ContextUtil.EnableCommit();
317   }
318   else
319   {
320   ContextUtil.DisableCommit();
321   }
322   }
323  
324   if (0 == --TransactionScopeCount)
325   {
326   if (_logger.IsDebugEnabled)
327   {
328   _logger.Debug("Leave in ServiceDomain ");
329   }
330  
331   ServiceDomain.Leave();
332   }
333  
334   _closed = true;
335   }
336   }
337  
338   /// <summary>
339   /// Complete (commit) a transsaction
340   /// </summary>
341 0 public void Complete()
342   {
343   this.Consistent = true;
344   }
345   #endregion
346  
347   #region IDisposable Members
348   /// <summary>
349   /// Implementation of IDisposable so that this class
350   /// can be used with C#'s using statement.
351   /// </summary>
352 0 void IDisposable.Dispose()
353   {
354   Close();
355   }
356   #endregion
357  
358   }
359   }
360