diff --git a/src/Spring/Spring.Data/Data/Core/AdoAccessor.cs b/src/Spring/Spring.Data/Data/Core/AdoAccessor.cs index efb10def7..6b0e28621 100644 --- a/src/Spring/Spring.Data/Data/Core/AdoAccessor.cs +++ b/src/Spring/Spring.Data/Data/Core/AdoAccessor.cs @@ -1,5 +1,5 @@ -#region License - +#region License + /* * Copyright © 2002-2006 the original author or authors. * @@ -14,106 +14,106 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - -#endregion - -using System; -using System.Data; -using Spring.Data.Common; -using Spring.Data.Support; -using Spring.Objects.Factory; - -namespace Spring.Data.Core -{ - /// - /// Base class for AdoTemplate and other ADO.NET DAO helper classes defining - /// common properties like DbProvider. - /// - /// Mark Pollack (.NET) - /// Juergen Hoeller - public abstract class AdoAccessor : IInitializingObject - { - protected object AdoUtils; - - protected int commandTimeout; - - #region Properties - - /// - /// An instance of a DbProvider implementation. - /// - public abstract IDbProvider DbProvider - { - get; - set; - } - - - - /// - /// Gets or sets a value indicating whether to lazily initialize the - /// IAdoExceptionTranslator for this accessor, on first encounter of a - /// exception from the data provider. Default is "true"; can be switched to - /// "false" for initialization on startup. - /// - /// true if to lazy initialize the IAdoExceptionTranslator; - /// otherwise, false. - public abstract bool LazyInit - { - get; - set; - } - - - /// - /// Gets or sets the exception translator. If no custom translator is provided, a default - /// is used. - /// - /// The exception translator. - public abstract IAdoExceptionTranslator ExceptionTranslator - { - get; - set; - } - - - /// - /// Gets or set the System.Type to use to create an instance of IDataReaderWrapper - /// for the purpose of having defaults values to use in case of DBNull values read - /// from IDataReader. - /// - /// The type of the data reader wrapper. - public abstract Type DataReaderWrapperType - { - get; - set; - } - - /// - /// Gets or sets the command timeout for IDbCommands that this AdoTemplate executes. - /// - /// Default is 0, indicating to use the database provider's default. - /// Any timeout specified here will be overridden by the remaining - /// transaction timeout when executing within a transaction that has a - /// timeout specified at the transaction level. - /// - /// The command timeout. - public virtual int CommandTimeout - { - get { return commandTimeout; } - set { commandTimeout = value; } - } - - #endregion - - /// - /// Prepare the command setting the transaction timeout. - /// - /// - protected virtual void ApplyCommandSettings(IDbCommand command) + */ + +#endregion + +using System; +using System.Data; +using Spring.Data.Common; +using Spring.Data.Support; +using Spring.Objects.Factory; + +namespace Spring.Data.Core +{ + /// + /// Base class for AdoTemplate and other ADO.NET DAO helper classes defining + /// common properties like DbProvider. + /// + /// Mark Pollack (.NET) + /// Juergen Hoeller + public abstract class AdoAccessor : IInitializingObject + { + protected object AdoUtils; + + protected int commandTimeout = -1; + + #region Properties + + /// + /// An instance of a DbProvider implementation. + /// + public abstract IDbProvider DbProvider + { + get; + set; + } + + + + /// + /// Gets or sets a value indicating whether to lazily initialize the + /// IAdoExceptionTranslator for this accessor, on first encounter of a + /// exception from the data provider. Default is "true"; can be switched to + /// "false" for initialization on startup. + /// + /// true if to lazy initialize the IAdoExceptionTranslator; + /// otherwise, false. + public abstract bool LazyInit + { + get; + set; + } + + + /// + /// Gets or sets the exception translator. If no custom translator is provided, a default + /// is used. + /// + /// The exception translator. + public abstract IAdoExceptionTranslator ExceptionTranslator + { + get; + set; + } + + + /// + /// Gets or set the System.Type to use to create an instance of IDataReaderWrapper + /// for the purpose of having defaults values to use in case of DBNull values read + /// from IDataReader. + /// + /// The type of the data reader wrapper. + public abstract Type DataReaderWrapperType { - Support.ConnectionUtils.ApplyTransactionTimeout(command, DbProvider, CommandTimeout); + get; + set; + } + + /// + /// Gets or sets the command timeout for IDbCommands that this AdoTemplate executes. + /// + /// Default is 0, indicating to use the database provider's default. + /// Any timeout specified here will be overridden by the remaining + /// transaction timeout when executing within a transaction that has a + /// timeout specified at the transaction level. + /// + /// The command timeout. + public virtual int CommandTimeout + { + get { return commandTimeout; } + set { commandTimeout = value; } + } + + #endregion + + /// + /// Prepare the command setting the transaction timeout. + /// + /// + protected virtual void ApplyCommandSettings(IDbCommand command) + { + Support.ConnectionUtils.ApplyTransactionTimeout(command, DbProvider, CommandTimeout); } /// @@ -130,22 +130,22 @@ protected virtual void DisposeCommand(IDbCommand command) protected virtual void DisposeDataAdapterCommands(IDbDataAdapter adapter) { Support.AdoUtils.DisposeDataAdapterCommands(adapter); - } - + } + /// /// Extract the command text from the given , if any. /// - protected virtual string GetCommandText(object cmdTextProvider) - { - ICommandTextProvider commandTextProvider = cmdTextProvider as ICommandTextProvider; - if (commandTextProvider != null) - { - return commandTextProvider.CommandText; - } - else - { - return null; - } + protected virtual string GetCommandText(object cmdTextProvider) + { + ICommandTextProvider commandTextProvider = cmdTextProvider as ICommandTextProvider; + if (commandTextProvider != null) + { + return commandTextProvider.CommandText; + } + else + { + return null; + } } /// @@ -155,95 +155,95 @@ protected virtual ConnectionTxPair GetConnectionTxPair(IDbProvider provider) { return Support.ConnectionUtils.GetConnectionTxPair(provider); } - - protected virtual void DisposeConnection(IDbConnection connection, IDbProvider provider) + + protected virtual void DisposeConnection(IDbConnection connection, IDbProvider provider) { Support.ConnectionUtils.DisposeConnection(connection, provider); - } - - /// - /// Invoked by an - /// after it has injected all of an object's dependencies. - /// - /// - ///

- /// This method allows the object instance to perform the kind of - /// initialization only possible when all of it's dependencies have - /// been injected (set), and to throw an appropriate exception in the - /// event of misconfiguration. - ///

- ///

- /// Please do consult the class level documentation for the - /// interface for a - /// description of exactly when this method is invoked. In - /// particular, it is worth noting that the - /// - /// and - /// callbacks will have been invoked prior to this method being - /// called. - ///

- ///
- /// - /// In the event of misconfiguration (such as the failure to set a - /// required property) or if initialization fails. - /// - public abstract void AfterPropertiesSet(); - - /// - /// Creates the data reader wrapper for use in AdoTemplate callback methods. - /// - /// The reader to wrap. - /// The data reader used in AdoTemplate callbacks - public abstract IDataReader CreateDataReaderWrapper(IDataReader readerToWrap); - - /// - /// Creates the a db parameters collection, adding to the collection a parameter created from - /// the method parameters. - /// - /// The name of the parameter - /// The type of the parameter. - /// The size of the parameter, for use in defining lengths of string values. Use - /// 0 if not applicable. - /// The parameter value. - /// A collection of db parameters with a single parameter in the collection based - /// on the method parameters - protected IDbParameters CreateDbParameters(string name, Enum dbType, int size, object parameterValue) - { - IDbParameters parameters = new DbParameters(DbProvider); - parameters.Add(name, dbType, size).Value = parameterValue; - return parameters; - } - - - #region Parameter Creation Helper Methods - - /// - /// Creates a new instance of - /// - /// a new instance of - public virtual IDbParameters CreateDbParameters() - { - return new DbParameters(DbProvider); - } - - /// - /// Derives the parameters of a stored procedure, not including the return parameter. - /// - /// Name of the procedure. - /// The stored procedure parameters. - public virtual IDataParameter[] DeriveParameters(string procedureName) - { - return DeriveParameters(procedureName, false); - } - - /// - /// Derives the parameters of a stored procedure including the return parameter - /// - /// Name of the procedure. - /// if set to true to include return parameter. - /// The stored procedure parameters - public abstract IDataParameter[] DeriveParameters(string procedureName, bool includeReturnParameter); - - #endregion - } -} + } + + /// + /// Invoked by an + /// after it has injected all of an object's dependencies. + /// + /// + ///

+ /// This method allows the object instance to perform the kind of + /// initialization only possible when all of it's dependencies have + /// been injected (set), and to throw an appropriate exception in the + /// event of misconfiguration. + ///

+ ///

+ /// Please do consult the class level documentation for the + /// interface for a + /// description of exactly when this method is invoked. In + /// particular, it is worth noting that the + /// + /// and + /// callbacks will have been invoked prior to this method being + /// called. + ///

+ ///
+ /// + /// In the event of misconfiguration (such as the failure to set a + /// required property) or if initialization fails. + /// + public abstract void AfterPropertiesSet(); + + /// + /// Creates the data reader wrapper for use in AdoTemplate callback methods. + /// + /// The reader to wrap. + /// The data reader used in AdoTemplate callbacks + public abstract IDataReader CreateDataReaderWrapper(IDataReader readerToWrap); + + /// + /// Creates the a db parameters collection, adding to the collection a parameter created from + /// the method parameters. + /// + /// The name of the parameter + /// The type of the parameter. + /// The size of the parameter, for use in defining lengths of string values. Use + /// 0 if not applicable. + /// The parameter value. + /// A collection of db parameters with a single parameter in the collection based + /// on the method parameters + protected IDbParameters CreateDbParameters(string name, Enum dbType, int size, object parameterValue) + { + IDbParameters parameters = new DbParameters(DbProvider); + parameters.Add(name, dbType, size).Value = parameterValue; + return parameters; + } + + + #region Parameter Creation Helper Methods + + /// + /// Creates a new instance of + /// + /// a new instance of + public virtual IDbParameters CreateDbParameters() + { + return new DbParameters(DbProvider); + } + + /// + /// Derives the parameters of a stored procedure, not including the return parameter. + /// + /// Name of the procedure. + /// The stored procedure parameters. + public virtual IDataParameter[] DeriveParameters(string procedureName) + { + return DeriveParameters(procedureName, false); + } + + /// + /// Derives the parameters of a stored procedure including the return parameter + /// + /// Name of the procedure. + /// if set to true to include return parameter. + /// The stored procedure parameters + public abstract IDataParameter[] DeriveParameters(string procedureName, bool includeReturnParameter); + + #endregion + } +} diff --git a/src/Spring/Spring.Data/Data/Support/ConnectionUtils.cs b/src/Spring/Spring.Data/Data/Support/ConnectionUtils.cs index 81db73c30..d8e472cd2 100644 --- a/src/Spring/Spring.Data/Data/Support/ConnectionUtils.cs +++ b/src/Spring/Spring.Data/Data/Support/ConnectionUtils.cs @@ -1,5 +1,5 @@ -#region License - +#region License + /* * Copyright © 2002-2005 the original author or authors. * @@ -14,231 +14,233 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - -#endregion - -using System; -using System.Data; -using Common.Logging; -using Spring.Data.Common; -using Spring.Transaction.Support; -using Spring.Util; - -namespace Spring.Data.Support -{ - /// - /// Summary description for DbProviderUtils. - /// - public abstract class ConnectionUtils - { - #region Logging - - private static readonly ILog LOG = LogManager.GetLogger(typeof (ConnectionUtils)); - - #endregion - - public static readonly int CONNECTION_SYNCHRONIZATION_ORDER = 1000; - /// - /// Dispose of the given Connection, created via the given IDbProvider, - /// if it is not managed externally (that is, not bound to the thread). - /// - /// The connection to close if necessary. If - /// this is null the call will be ignored. - /// The IDbProvider the connection came from - public static void DisposeConnection(IDbConnection conn, IDbProvider dbProvider) - { - try - { - DoDisposeConnection(conn, dbProvider); - } catch (Exception e) - { - LOG.Warn("Could not close connection", e); - } - - } - private static void DoDisposeConnection(IDbConnection conn, IDbProvider dbProvider) - { - if (conn == null) - { - return; - } - - if (dbProvider != null) - { - ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.GetResource(dbProvider); - if (conHolder != null && ConnectionEquals(conHolder.Connection, conn)) - { - // It's the transactional connection bound to the thread so don't close it. - conHolder.Released(); - return; - } - } - if (LOG.IsDebugEnabled) - { - LOG.Debug("Disposing of IDbConnection with connection string = [" + dbProvider.ConnectionString + "]"); - } - conn.Dispose(); - } - - - /// - /// Get a ADO.NET Connection/Transaction Pair for the given IDbProvider. - /// Changes any exception into the Spring hierarchy of generic data access - /// exceptions, simplifying calling code and making any exception that is - /// thrown more meaningful. - /// - /// - /// Is aware of a corresponding Connection/Transaction bound to the current thread, for example - /// when using AdoPlatformTransactionManager. Will bind a IDbConnection to the thread - /// if transaction synchronization is active - /// - /// The provider. - /// A Connection/Transaction pair. - public static ConnectionTxPair GetConnectionTxPair(IDbProvider provider) - { - try - { - return DoGetConnection(provider); - } catch (Exception e) - { - throw new CannotGetAdoConnectionException("Could not get ADO.NET connection.", e); - } - - } - - - /// - /// Get a ADO.NET Connection/Transaction Pair for the given IDbProvider. - /// Same as but throwing original provider - /// exception. - /// - /// - /// Is aware of a corresponding Connection/Transaction bound to the current thread, for example - /// when using AdoPlatformTransactionManager. Will bind a IDbConnection to the thread - /// if transaction synchronization is active - /// - /// The provider. - /// - public static ConnectionTxPair DoGetConnection(IDbProvider provider) - { - AssertUtils.ArgumentNotNull(provider, "provider"); - ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.GetResource(provider); - if (conHolder != null && (conHolder.HasConnection || conHolder.SynchronizedWithTransaction)) - { - conHolder.Requested(); - if (!conHolder.HasConnection) - { - if (LOG.IsDebugEnabled) - { - LOG.Debug("Fetching resumed ADO.NET connection from DbProvider"); - } - conHolder.Connection = provider.CreateConnection(); - } - return new ConnectionTxPair(conHolder.Connection, conHolder.Transaction); - } - - // Else we either got no holder or an empty thread-bound holder here. - if (LOG.IsDebugEnabled) - { - LOG.Debug("Fetching Connection from DbProvider"); - } - IDbConnection conn = provider.CreateConnection(); - conn.Open(); - - if (TransactionSynchronizationManager.SynchronizationActive) - { - LOG.Debug("Registering transaction synchronization for IDbConnection"); - //Use same connection for further ADO.NET actions with the transaction. - //Thread-bound object will get removed by manager at transaction completion. - - ConnectionHolder holderToUse = conHolder; - if (holderToUse == null) - { - holderToUse = new ConnectionHolder(conn, null); - } - else - { - holderToUse.Connection = conn; - } - holderToUse.Requested(); - TransactionSynchronizationManager.RegisterSynchronization( - new ConnectionSynchronization(holderToUse, provider)); - holderToUse.SynchronizedWithTransaction = true; - if (holderToUse != conHolder) - { - TransactionSynchronizationManager.BindResource(provider, holderToUse); - } - - } - return new ConnectionTxPair(conn, null); - } - - /// - /// Do the connection mgmt. - /// - /// - /// - public static IDbConnection GetConnection(IDbProvider provider) - { - AssertUtils.ArgumentNotNull(provider, "provider"); - - return GetConnectionTxPair(provider).Connection; - - } - - private static bool ConnectionEquals(IDbConnection heldCon, IDbConnection passedInCon) - { - return (heldCon == passedInCon || heldCon.Equals(passedInCon) || - getTargetConnection(heldCon).Equals(passedInCon)); - } - - private static IDbConnection getTargetConnection(IDbConnection con) - { - IDbConnection conToUse = con; + */ + +#endregion + +using System; +using System.Data; +using Common.Logging; +using Spring.Data.Common; +using Spring.Transaction.Support; +using Spring.Util; + +namespace Spring.Data.Support +{ + /// + /// Summary description for DbProviderUtils. + /// + public abstract class ConnectionUtils + { + #region Logging + + private static readonly ILog LOG = LogManager.GetLogger(typeof(ConnectionUtils)); + + #endregion + + public static readonly int CONNECTION_SYNCHRONIZATION_ORDER = 1000; + /// + /// Dispose of the given Connection, created via the given IDbProvider, + /// if it is not managed externally (that is, not bound to the thread). + /// + /// The connection to close if necessary. If + /// this is null the call will be ignored. + /// The IDbProvider the connection came from + public static void DisposeConnection(IDbConnection conn, IDbProvider dbProvider) + { + try + { + DoDisposeConnection(conn, dbProvider); + } + catch (Exception e) + { + LOG.Warn("Could not close connection", e); + } + + } + private static void DoDisposeConnection(IDbConnection conn, IDbProvider dbProvider) + { + if (conn == null) + { + return; + } + + if (dbProvider != null) + { + ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.GetResource(dbProvider); + if (conHolder != null && ConnectionEquals(conHolder.Connection, conn)) + { + // It's the transactional connection bound to the thread so don't close it. + conHolder.Released(); + return; + } + } + if (LOG.IsDebugEnabled) + { + LOG.Debug("Disposing of IDbConnection with connection string = [" + dbProvider.ConnectionString + "]"); + } + conn.Dispose(); + } + + + /// + /// Get a ADO.NET Connection/Transaction Pair for the given IDbProvider. + /// Changes any exception into the Spring hierarchy of generic data access + /// exceptions, simplifying calling code and making any exception that is + /// thrown more meaningful. + /// + /// + /// Is aware of a corresponding Connection/Transaction bound to the current thread, for example + /// when using AdoPlatformTransactionManager. Will bind a IDbConnection to the thread + /// if transaction synchronization is active + /// + /// The provider. + /// A Connection/Transaction pair. + public static ConnectionTxPair GetConnectionTxPair(IDbProvider provider) + { + try + { + return DoGetConnection(provider); + } + catch (Exception e) + { + throw new CannotGetAdoConnectionException("Could not get ADO.NET connection.", e); + } + + } + + + /// + /// Get a ADO.NET Connection/Transaction Pair for the given IDbProvider. + /// Same as but throwing original provider + /// exception. + /// + /// + /// Is aware of a corresponding Connection/Transaction bound to the current thread, for example + /// when using AdoPlatformTransactionManager. Will bind a IDbConnection to the thread + /// if transaction synchronization is active + /// + /// The provider. + /// + public static ConnectionTxPair DoGetConnection(IDbProvider provider) + { + AssertUtils.ArgumentNotNull(provider, "provider"); + ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.GetResource(provider); + if (conHolder != null && (conHolder.HasConnection || conHolder.SynchronizedWithTransaction)) + { + conHolder.Requested(); + if (!conHolder.HasConnection) + { + if (LOG.IsDebugEnabled) + { + LOG.Debug("Fetching resumed ADO.NET connection from DbProvider"); + } + conHolder.Connection = provider.CreateConnection(); + } + return new ConnectionTxPair(conHolder.Connection, conHolder.Transaction); + } + + // Else we either got no holder or an empty thread-bound holder here. + if (LOG.IsDebugEnabled) + { + LOG.Debug("Fetching Connection from DbProvider"); + } + IDbConnection conn = provider.CreateConnection(); + conn.Open(); + + if (TransactionSynchronizationManager.SynchronizationActive) + { + LOG.Debug("Registering transaction synchronization for IDbConnection"); + //Use same connection for further ADO.NET actions with the transaction. + //Thread-bound object will get removed by manager at transaction completion. + + ConnectionHolder holderToUse = conHolder; + if (holderToUse == null) + { + holderToUse = new ConnectionHolder(conn, null); + } + else + { + holderToUse.Connection = conn; + } + holderToUse.Requested(); + TransactionSynchronizationManager.RegisterSynchronization( + new ConnectionSynchronization(holderToUse, provider)); + holderToUse.SynchronizedWithTransaction = true; + if (holderToUse != conHolder) + { + TransactionSynchronizationManager.BindResource(provider, holderToUse); + } + + } + return new ConnectionTxPair(conn, null); + } + + /// + /// Do the connection mgmt. + /// + /// + /// + public static IDbConnection GetConnection(IDbProvider provider) + { + AssertUtils.ArgumentNotNull(provider, "provider"); + + return GetConnectionTxPair(provider).Connection; + + } + + private static bool ConnectionEquals(IDbConnection heldCon, IDbConnection passedInCon) + { + return (heldCon == passedInCon || heldCon.Equals(passedInCon) || + getTargetConnection(heldCon).Equals(passedInCon)); + } + + private static IDbConnection getTargetConnection(IDbConnection con) + { + IDbConnection conToUse = con; /* while (conToUse is ConnectionProxy) { conToUse = (ConnectionProxy)conToUse.getTargetConnection(); } - */ - return conToUse; - } - - /// - /// Applies the current transaction timeout, if any, to the given ADO.NET IDbCommand object. - /// - /// The command. - /// The db provider. - public static void ApplyTransactionTimeout(IDbCommand command, IDbProvider dbProvider) - { - ApplyTransactionTimeout(command, dbProvider, 0); - } - - /// - /// Applies the specified timeout - overridden by the current transaction timeout, if any, to to the - /// given ADO.NET IDb command object. - /// - /// The command. - /// The db provider the command was obtained from. - /// The timeout to apply (or 0 for no timeout outside of a transaction. - public static void ApplyTransactionTimeout(IDbCommand command, IDbProvider dbProvider, int timeout) - { - AssertUtils.ArgumentNotNull(command, "command", "No IDbCommand specified."); - AssertUtils.ArgumentNotNull(dbProvider, "dbProvider", "No IDbProvider specified."); - - ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.GetResource(dbProvider); - if (conHolder != null && conHolder.HasTimeout) - { - // Remaining transaction timeout overrides specified value. - command.CommandTimeout = conHolder.TimeToLiveInSeconds; - } - else if (timeout >= 0) - { - // No current transaction timeout -> apply specified value. 0 = infinite timeout in some drivers. - command.CommandTimeout = timeout; - } - - } - } -} + */ + return conToUse; + } + + /// + /// Applies the current transaction timeout, if any, to the given ADO.NET IDbCommand object. + /// + /// The command. + /// The db provider. + public static void ApplyTransactionTimeout(IDbCommand command, IDbProvider dbProvider) + { + ApplyTransactionTimeout(command, dbProvider, 0); + } + + /// + /// Applies the specified timeout - overridden by the current transaction timeout, if any, to to the + /// given ADO.NET IDb command object. + /// + /// The command. + /// The db provider the command was obtained from. + /// The timeout to apply (or 0 for no timeout outside of a transaction. + public static void ApplyTransactionTimeout(IDbCommand command, IDbProvider dbProvider, int timeout) + { + AssertUtils.ArgumentNotNull(command, "command", "No IDbCommand specified."); + AssertUtils.ArgumentNotNull(dbProvider, "dbProvider", "No IDbProvider specified."); + + ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.GetResource(dbProvider); + if (conHolder != null && conHolder.HasTimeout) + { + // Remaining transaction timeout overrides specified value. + command.CommandTimeout = conHolder.TimeToLiveInSeconds; + } + else if (timeout != -1) + { + // No current transaction timeout -> apply specified value. 0 = infinite timeout in some drivers. + command.CommandTimeout = timeout; + } + + } + } +}