PageRenderTime 50ms CodeModel.GetById 17ms app.highlight 17ms RepoModel.GetById 5ms app.codeStats 0ms

/Rhino.Etl.Core/Infrastructure/Use.cs

http://github.com/ayende/rhino-etl
C# | 260 lines | 141 code | 28 blank | 91 comment | 24 complexity | 05b81833d39aac6a845fbbb6db5f7d10 MD5 | raw file
  1using System;
  2using System.Configuration;
  3using System.Data;
  4
  5namespace Rhino.Etl.Core.Infrastructure
  6{
  7    using System.Data.Common;
  8
  9    /// <summary>
 10    /// Helper class to provide simple data access, when we want to access the ADO.Net
 11    /// library directly. 
 12    /// </summary>
 13    public static class Use
 14    {
 15        #region Delegates
 16
 17        /// <summary>
 18        /// Delegate to execute an action with a command
 19        /// and return a result: <typeparam name="T"/>
 20        /// </summary>
 21        public delegate T Func<T>(IDbCommand command);
 22
 23        /// <summary>
 24        /// Delegate to execute an action with a command
 25        /// </summary>
 26        public delegate void Proc(IDbCommand command);
 27
 28        #endregion
 29
 30        /// <summary>
 31        /// Gets or sets the active connection.
 32        /// </summary>
 33        /// <value>The active connection.</value>
 34        [ThreadStatic]
 35        private static IDbConnection ActiveConnection;
 36
 37        /// <summary>
 38        /// Gets or sets the active transaction.
 39        /// </summary>
 40        /// <value>The active transaction.</value>
 41        [ThreadStatic] 
 42        private static IDbTransaction ActiveTransaction;
 43
 44        /// <summary>
 45        /// Gets or sets the transaction counter.
 46        /// </summary>
 47        /// <value>The transaction counter.</value>
 48        [ThreadStatic]
 49        private static int TransactionCounter;
 50
 51        /// <summary>
 52        /// Execute the specified delegate inside a transaction and return 
 53        /// the result of the delegate.
 54        /// </summary>
 55        /// <typeparam name="T"></typeparam>
 56        /// <param name="connectionStringName">The name of the named connection string in the configuration file</param>
 57        /// <param name="actionToExecute">The action to execute</param>
 58        /// <returns></returns>
 59        public static T Transaction<T>(string connectionStringName, Func<T> actionToExecute)
 60        {
 61            T result = default(T);
 62
 63            ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[connectionStringName];
 64            if (connectionStringSettings == null)
 65                throw new InvalidOperationException("Could not find connnection string: " + connectionStringName);
 66
 67            Transaction(connectionStringSettings, delegate(IDbCommand command) { result = actionToExecute(command); });
 68            return result;
 69        }
 70
 71        /// <summary>
 72        /// Execute the specified delegate inside a transaction and return 
 73        /// the result of the delegate.
 74        /// </summary>
 75        /// <typeparam name="T"></typeparam>
 76        /// <param name="connectionStringSettings">The connection string settings to use for the connection</param>
 77        /// <param name="actionToExecute">The action to execute</param>
 78        /// <returns></returns>
 79        public static T Transaction<T>(ConnectionStringSettings connectionStringSettings, Func<T> actionToExecute)
 80        {
 81            T result = default(T);
 82            Transaction(connectionStringSettings, delegate(IDbCommand command) { result = actionToExecute(command); });
 83            return result;
 84        }
 85
 86        /// <summary>
 87        /// Execute the specified delegate inside a transaction
 88        /// </summary>
 89        /// <param name="connectionStringName">Name of the connection string.</param>
 90        /// <param name="actionToExecute">The action to execute.</param>
 91        public static void Transaction(string connectionStringName, Proc actionToExecute)
 92        {
 93            ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[connectionStringName];
 94            if (connectionStringSettings == null)
 95                throw new InvalidOperationException("Could not find connnection string: " + connectionStringName);
 96
 97            Transaction(connectionStringSettings, IsolationLevel.Unspecified, actionToExecute);
 98        }
 99
100        /// <summary>
101        /// Execute the specified delegate inside a transaction
102        /// </summary>
103        /// <param name="connectionStringSettings">The connection string settings to use for the connection</param>
104        /// <param name="actionToExecute">The action to execute.</param>
105        public static void Transaction(ConnectionStringSettings connectionStringSettings, Proc actionToExecute)
106        {
107            Transaction(connectionStringSettings, IsolationLevel.Unspecified, actionToExecute);
108        }
109
110        /// <summary>
111        /// Execute the specified delegate inside a transaction with the specific
112        /// isolation level 
113        /// </summary>
114        /// <param name="connectionStringName">Name of the connection string.</param>
115        /// <param name="isolationLevel">The isolation level.</param>
116        /// <param name="actionToExecute">The action to execute.</param>
117        public static void Transaction(string connectionStringName, IsolationLevel isolationLevel, Proc actionToExecute)
118        {
119            ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[connectionStringName];
120            if (connectionStringSettings == null)
121                throw new InvalidOperationException("Could not find connnection string: " + connectionStringName);
122
123            Transaction(connectionStringSettings, isolationLevel, actionToExecute);
124        }
125
126        /// <summary>
127        /// Execute the specified delegate inside a transaction with the specific
128        /// isolation level 
129        /// </summary>
130        /// <param name="connectionStringSettings">Connection string settings node to use for the connection</param>
131        /// <param name="isolationLevel">The isolation level.</param>
132        /// <param name="actionToExecute">The action to execute.</param>
133        public static void Transaction(ConnectionStringSettings connectionStringSettings, IsolationLevel isolationLevel, Proc actionToExecute)
134        {
135            StartTransaction(connectionStringSettings, isolationLevel);
136            try
137            {
138                using (IDbCommand command = ActiveConnection.CreateCommand())
139                {
140                    command.Transaction = ActiveTransaction;
141                    actionToExecute(command);
142                }
143                CommitTransaction();
144            }
145            catch
146            {
147                RollbackTransaction();
148                throw;
149            }
150            finally
151            {
152                DisposeTransaction();
153            }
154        }
155
156        /// <summary>
157        /// Disposes the transaction.
158        /// </summary>
159        private static void DisposeTransaction()
160        {
161            if (TransactionCounter <= 0)
162            {
163                ActiveConnection.Dispose();
164                ActiveConnection = null;
165            }
166        }
167
168        /// <summary>
169        /// Rollbacks the transaction.
170        /// </summary>
171        private static void RollbackTransaction()
172        {
173            ActiveTransaction.Rollback();
174            ActiveTransaction.Dispose();
175            ActiveTransaction = null;
176            TransactionCounter = 0;
177        }
178
179        /// <summary>
180        /// Commits the transaction.
181        /// </summary>
182        private static void CommitTransaction()
183        {
184            TransactionCounter--;
185            if (TransactionCounter == 0 && ActiveTransaction != null)
186            {
187                ActiveTransaction.Commit();
188                ActiveTransaction.Dispose();
189                ActiveTransaction = null;
190            }
191        }
192
193        /// <summary>
194        /// Starts the transaction.
195        /// </summary>
196        /// <param name="connectionStringSettings">The connection string settings to use for the transaction</param>
197        /// <param name="isolation">The isolation.</param>
198        private static void StartTransaction(ConnectionStringSettings connectionStringSettings, IsolationLevel isolation)
199        {
200            if (TransactionCounter <= 0)
201            {
202                TransactionCounter = 0;
203                ActiveConnection = Connection(connectionStringSettings);
204                ActiveTransaction = ActiveConnection.BeginTransaction(isolation);
205            }
206            TransactionCounter++;
207        }
208
209        /// <summary>
210        /// Creates an open connection for a given named connection string, using the provider name
211        /// to select the proper implementation
212        /// </summary>
213        /// <param name="name">The name.</param>
214        /// <returns>The open connection</returns>
215        public static IDbConnection Connection(string name)
216        {
217            ConnectionStringSettings connectionString = ConfigurationManager.ConnectionStrings[name];
218            if (connectionString == null)
219                throw new InvalidOperationException("Could not find connnection string: " + name);
220
221            return Connection(connectionString);
222        }
223
224        /// <summary>
225        /// Creates an open connection for a given connection string setting, using the provider
226        /// name of select the proper implementation
227        /// </summary>
228        /// <param name="connectionString">ConnectionStringSetting node</param>
229        /// <returns>The open connection</returns>
230        public static IDbConnection Connection(ConnectionStringSettings connectionString)
231        {
232            if (connectionString == null)
233                throw new InvalidOperationException("Null ConnectionStringSettings specified");
234            if (connectionString.ProviderName == null)
235                throw new InvalidOperationException("Null ProviderName specified");
236
237            IDbConnection connection = null;
238
239            string providerName = connectionString.ProviderName;
240            if (providerName != null)
241            {
242                // Backwards compatibility: ProviderName could be an assembly qualified connection type name.
243                Type connectionType = Type.GetType(providerName);
244                if (connectionType != null)
245                {
246                    connection = Activator.CreateInstance(connectionType) as IDbConnection;
247                }
248            }
249            if (connection == null)
250            {
251                // ADO.NET compatible usage of provider name.
252                connection = DbProviderFactories.GetFactory(providerName).CreateConnection();
253            }
254
255            connection.ConnectionString = connectionString.ConnectionString;
256            connection.Open();
257            return connection;
258        }
259    }
260}