Author: rgrabowski Date: Sun Feb 17 13:49:35 2008 New Revision: 628555 URL: http://svn.apache.org/viewvc?rev=628555&view=rev Log: Fix for LOG4NET-141. Added CreateConnection method that accepts the resolved connection Type and the resolved connection string to allow sub-classes more control on how the IDbConnection is created. Refactored duplicate code for closing/disposing the IDbCommand and IDbConnection objects into DisposeCommand/Connection.
Modified: logging/log4net/trunk/src/Appender/AdoNetAppender.cs Modified: logging/log4net/trunk/src/Appender/AdoNetAppender.cs URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Appender/AdoNetAppender.cs?rev=628555&r1=628554&r2=628555&view=diff ============================================================================== --- logging/log4net/trunk/src/Appender/AdoNetAppender.cs (original) +++ logging/log4net/trunk/src/Appender/AdoNetAppender.cs Sun Feb 17 13:49:35 2008 @@ -174,7 +174,7 @@ } /// <summary> - /// + /// The appSettings key from App.Config that contains the connection string. /// </summary> public string AppSettingsKey { @@ -184,8 +184,11 @@ #if NET_2_0 /// <summary> - /// + /// The connectionStrings key from App.Config that contains the connection string. /// </summary> + /// <remarks> + /// This property requires at least .NET 2.0. + /// </remarks> public string ConnectionStringName { get { return m_connectionStringName; } @@ -373,8 +376,8 @@ /// </remarks> protected IDbConnection Connection { - get { return this.m_dbConnection; } - set { this.m_dbConnection = value; } + get { return m_dbConnection; } + set { m_dbConnection = value; } } #endregion // Protected Instance Properties @@ -428,32 +431,8 @@ override protected void OnClose() { base.OnClose(); - - // Close the cached command and connection objects - if (m_dbCommand != null) - { - try - { - m_dbCommand.Dispose(); - } - catch (Exception ex) - { - LogLog.Warn(declaringType, "Exception while disposing cached command object", ex); - } - m_dbCommand = null; - } - if (m_dbConnection != null) - { - try - { - m_dbConnection.Close(); - } - catch (Exception ex) - { - LogLog.Warn(declaringType, "Exception while disposing cached connection object", ex); - } - m_dbConnection = null; - } + DisposeCommand(false); + DiposeConnection(); } #endregion @@ -474,7 +453,7 @@ { if (m_reconnectOnError && (m_dbConnection == null || m_dbConnection.State != ConnectionState.Open)) { - LogLog.Debug(declaringType, "Attempting to reconnect to database. Current Connection State: " + ((m_dbConnection==null)?"<null>":m_dbConnection.State.ToString()) ); + LogLog.Debug(declaringType, "Attempting to reconnect to database. Current Connection State: " + ((m_dbConnection==null)?SystemInfo.NullText:m_dbConnection.State.ToString()) ); InitializeDatabaseConnection(); InitializeDatabaseCommand(); @@ -637,73 +616,31 @@ } } - /// <summary> - /// Connects to the database. - /// </summary> - private void InitializeDatabaseConnection() - { - string connectionStringContext = "Unable to determine connection string context."; - string resolvedConnectionString = string.Empty; - - try - { - // Cleanup any existing command or connection - if (m_dbCommand != null) - { - try - { - m_dbCommand.Dispose(); - } - catch (Exception ex) - { - LogLog.Warn(declaringType, "Exception while disposing cached command object", ex); - } - m_dbCommand = null; - } - if (m_dbConnection != null) - { - try - { - m_dbConnection.Close(); - } - catch (Exception ex) - { - LogLog.Warn(declaringType, "Exception while disposing cached connection object", ex); - } - m_dbConnection = null; - } - - // Create the connection object - m_dbConnection = (IDbConnection)Activator.CreateInstance(ResolveConnectionType()); - - // Set the connection string - resolvedConnectionString = ResolveConnectionString(out connectionStringContext); - m_dbConnection.ConnectionString = resolvedConnectionString; - - using(SecurityContext.Impersonate(this)) - { - // Open the database connection - m_dbConnection.Open(); - } - } - catch (System.Exception e) - { - // Sadly, your connection string is bad. - ErrorHandler.Error("Could not open database connection [" + resolvedConnectionString + "]. Connection string context [" + connectionStringContext + "].", e); - - m_dbConnection = null; - } - } - /// <summary> + /// Creates an <see cref="IDbConnection"/> instance used to connect to the database. + /// </summary> + /// <remarks> + /// This method is called whenever a new IDbConnection is needed (i.e. when a reconnect is necessary). + /// </remarks> + /// <param name="connectionType">The <see cref="Type"/> of the <see cref="IDbConnection"/> object.</param> + /// <param name="connectionString">The connectionString output from the ResolveConnectionString method.</param> + /// <returns>An <see cref="IDbConnection"/> instance with a valid connection string.</returns> + virtual protected IDbConnection CreateConnection(Type connectionType, string connectionString) + { + IDbConnection connection = (IDbConnection)Activator.CreateInstance(connectionType); + connection.ConnectionString = connectionString; + return connection; + } + + /// <summary> /// Resolves the connection string from the ConnectionString, ConnectionStringName, or AppSettingsKey /// property. /// </summary> /// <remarks> - /// ConnectiongStringName is only supported on .NET 2.0. + /// ConnectiongStringName is only supported on .NET 2.0 and higher. /// </remarks> /// <param name="connectionStringContext">Additional information describing the connection string.</param> - /// <returns></returns> + /// <returns>A connection string used to connect to the database.</returns> virtual protected string ResolveConnectionString(out string connectionStringContext) { if (m_connectionString != null && m_connectionString.Length > 0) @@ -771,116 +708,163 @@ } } - /// <summary> - /// Prepares the database command and initialize the parameters. - /// </summary> - private void InitializeDatabaseCommand() - { - if (m_dbConnection != null && m_usePreparedCommand) - { - try - { - // Cleanup any existing command or connection - if (m_dbCommand != null) - { - try - { - m_dbCommand.Dispose(); - } - catch (Exception ex) - { - LogLog.Warn(declaringType, "Exception while disposing cached command object", ex); - } - m_dbCommand = null; - } + #endregion // Protected Instance Methods - // Create the command object - m_dbCommand = m_dbConnection.CreateCommand(); - - // Set the command string - m_dbCommand.CommandText = m_commandText; + #region Private Instance Methods - // Set the command type - m_dbCommand.CommandType = m_commandType; - } - catch(System.Exception e) - { - ErrorHandler.Error("Could not create database command ["+m_commandText+"]", e); + /// <summary> + /// Prepares the database command and initialize the parameters. + /// </summary> + private void InitializeDatabaseCommand() + { + if (m_dbConnection != null && m_usePreparedCommand) + { + try + { + DisposeCommand(false); - if (m_dbCommand != null) - { - try - { - m_dbCommand.Dispose(); - } - catch - { - // Ignore exception - } - m_dbCommand = null; - } - } + // Create the command object + m_dbCommand = m_dbConnection.CreateCommand(); - if (m_dbCommand != null) - { - try - { - foreach(AdoNetAppenderParameter param in m_parameters) - { - try - { - param.Prepare(m_dbCommand); - } - catch(System.Exception e) - { - ErrorHandler.Error("Could not add database command parameter ["+param.ParameterName+"]", e); - throw; - } - } - } - catch - { - try - { - m_dbCommand.Dispose(); - } - catch - { - // Ignore exception - } - m_dbCommand = null; - } - } + // Set the command string + m_dbCommand.CommandText = m_commandText; - if (m_dbCommand != null) - { - try - { - // Prepare the command statement. - m_dbCommand.Prepare(); - } - catch (System.Exception e) - { - ErrorHandler.Error("Could not prepare database command ["+m_commandText+"]", e); - try - { - m_dbCommand.Dispose(); - } - catch - { - // Ignore exception - } - m_dbCommand = null; - } - } - } - } + // Set the command type + m_dbCommand.CommandType = m_commandType; + } + catch (Exception e) + { + ErrorHandler.Error("Could not create database command [" + m_commandText + "]", e); - #endregion // Protected Instance Methods + DisposeCommand(true); + } + + if (m_dbCommand != null) + { + try + { + foreach (AdoNetAppenderParameter param in m_parameters) + { + try + { + param.Prepare(m_dbCommand); + } + catch (Exception e) + { + ErrorHandler.Error("Could not add database command parameter [" + param.ParameterName + "]", e); + throw; + } + } + } + catch + { + DisposeCommand(true); + } + } - #region Protected Instance Fields + if (m_dbCommand != null) + { + try + { + // Prepare the command statement. + m_dbCommand.Prepare(); + } + catch (Exception e) + { + ErrorHandler.Error("Could not prepare database command [" + m_commandText + "]", e); - /// <summary> + DisposeCommand(true); + } + } + } + } + + /// <summary> + /// Connects to the database. + /// </summary> + private void InitializeDatabaseConnection() + { + string connectionStringContext = "Unable to determine connection string context."; + string resolvedConnectionString = string.Empty; + + try + { + DisposeCommand(true); + DiposeConnection(); + + // Set the connection string + resolvedConnectionString = ResolveConnectionString(out connectionStringContext); + + m_dbConnection = CreateConnection(ResolveConnectionType(), resolvedConnectionString); + + using (SecurityContext.Impersonate(this)) + { + // Open the database connection + m_dbConnection.Open(); + } + } + catch (Exception e) + { + // Sadly, your connection string is bad. + ErrorHandler.Error("Could not open database connection [" + resolvedConnectionString + "]. Connection string context [" + connectionStringContext + "].", e); + + m_dbConnection = null; + } + } + + /// <summary> + /// Cleanup the existing command. + /// </summary> + /// <param name="ignoreException"> + /// If true, a message will be written using LogLog.Warn if an exception is encountered when calling Dispose. + /// </param> + private void DisposeCommand(bool ignoreException) + { + // Cleanup any existing command or connection + if (m_dbCommand != null) + { + try + { + m_dbCommand.Dispose(); + } + catch (Exception ex) + { + if (!ignoreException) + { + LogLog.Warn(declaringType, "Exception while disposing cached command object", ex); + } + } + m_dbCommand = null; + } + } + + /// <summary> + /// Cleanup the existing connection. + /// </summary> + /// <remarks> + /// Calls the IDbConnection's <see cref="IDbConnection.Close"/> method. + /// </remarks> + private void DiposeConnection() + { + if (m_dbConnection != null) + { + try + { + m_dbConnection.Close(); + } + catch (Exception ex) + { + LogLog.Warn(declaringType, "Exception while disposing cached connection object", ex); + } + m_dbConnection = null; + } + } + + #endregion // Private Instance Methods + + #region Protected Instance Fields + + /// <summary> /// Flag to indicate if we are using a command object /// </summary> /// <remarks> @@ -927,13 +911,13 @@ private string m_connectionString; /// <summary> - /// + /// The appSettings key from App.Config that contains the connection string. /// </summary> private string m_appSettingsKey; #if NET_2_0 /// <summary> - /// + /// The connectionStrings key from App.Config that contains the connection string. /// </summary> private string m_connectionStringName; #endif