Modify Log4Net AdoNetAppender Connection String at run-time

Log4Net

In my every day development I always have to figure out ways to keep my connection information in sync with the environment my application is deployed to.  We currently go through 3 environments; Dev, Test, and Production.  Each with a different set of database and service connections.  Today I was working on setting up Log4Net to use the AdoNetAppender and wanted to have it’s connection string move with my ApplicationSettings so that it would point to the appropriate database for the environment.  After about 3 hours of searching and code pounding I came up with a solution and since it was so hard to find I wanted to share what I learned.

First a little background of how my application is setup.  I have created the following application settings;

  • RunEnvironment: used to show where we are deployed, valid values are Development, Test, or Production
  • Database_Development: stores the database connection for development
  • Database_Test: stores the database connection for test
  • Database_Production: stores the database connection for Production

I also have a static ApplicationSettings class like this:

   1:  using System.Collections.Specialized;      
   2:  using System.Configuration;      
   3:   
   4:  public static class ApplicationSettings
   5:  {
   6:      private static readonly NameValueCollection Settings = ConfigurationManager.AppSettings;
   7:   
   8:      public static string RunEnvironment
   9:      {
  10:          get { return Settings["RunEnvironment"]; }
  11:      }
  12:      
  13:      public static string DatabaseConnectionString
  14:      {
  15:          get { return Settings["Database_" + RunEnvironment]; }
  16:      }
  17:  }

This approach allows me to just ask ApplicationSettings for the DatabaseConnectionString and it is always adjusted for the correct RunEnvironment.

Ok, so now to the Log4Net goodness.  I used the XML Configuration in my app.config to configure Log4Net and tried several ways to get the currently active configuration and manipulate it to reflect the new database connection string.  The solution that finally worked was to implement my own AdoNetAppender derived from the AdoNetAppender and override the ConnectionString Property.

Here is the new CustomAdoNetAppender class:

   1:  using log4net.Appender;
   2:   
   3:  public class CustomAdoNetAppender : AdoNetAppender
   4:  {
   5:      public new string ConnectionString
   6:      {
   7:          get
   8:          {
   9:              return base.ConnectionString;
  10:          }
  11:          set
  12:          {
  13:              base.ConnectionString = ApplicationSettings.DatabaseConnectionString;
  14:          }
  15:      }
  16:  }

 

The next step, which was left out of many of the post regarding this matter, was to modify the Log4Net configuration in your app/web.config to use the new CustomAdoNetAppender like below:

This must be added to the Configuration->ConfigSections of you config file

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />

After the Configuration->ConfigSections and at the same level in your config file add the Log4Net

   1:  <log4net>
   2:      <appender name="CustomAdoNetAppender" type="MyCustomNamespace.CustomAdoNetAppender">
   3:        <bufferSize value="100" />
   4:        <connectionType value="System.Data.SqlClient.SqlConnection, System.Data,  />
   5:        Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
   6:        <connectionString value="data source=[DbServer];initial catalog=[DbName]; />
   7:        integrated security=false;persist security info=True;User ID=[DB_USER];Password=[DB_PASS]"
   8:        <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger],[Message],[Exception])  />
   9:        VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)"
  10:        <parameter>
  11:          <parameterName value="@log_date" />
  12:          <dbType value="DateTime" />
  13:          <layout type="log4net.Layout.RawTimeStampLayout" />
  14:        </parameter>
  15:        <parameter>
  16:          <parameterName value="@thread" />
  17:          <dbType value="String" />
  18:          <size value="255" />
  19:          <layout type="log4net.Layout.PatternLayout">
  20:            <conversionPattern value="%thread" />
  21:          </layout>
  22:        </parameter>
  23:        <parameter>
  24:          <parameterName value="@log_level" />
  25:          <dbType value="String" />
  26:          <size value="50" />
  27:          <layout type="log4net.Layout.PatternLayout">
  28:            <conversionPattern value="%level" />
  29:          </layout>
  30:        </parameter>
  31:        <parameter>
  32:          <parameterName value="@logger" />
  33:          <dbType value="String" />
  34:          <size value="255" />
  35:          <layout type="log4net.Layout.PatternLayout">
  36:            <conversionPattern value="%logger" />
  37:          </layout>
  38:        </parameter>
  39:        <parameter>
  40:          <parameterName value="@message" />
  41:          <dbType value="String" />
  42:          <size value="4000" />
  43:          <layout type="log4net.Layout.PatternLayout">
  44:            <conversionPattern value="%message" />
  45:          </layout>
  46:        </parameter>
  47:        <parameter>
  48:          <parameterName value="@exception" />
  49:          <dbType value="String" />
  50:          <size value="2000" />
  51:          <layout type="log4net.Layout.ExceptionLayout" />
  52:        </parameter>
  53:      </appender>
  54:      <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
  55:        <layout type="log4net.Layout.PatternLayout">
  56:          <param name="Header" value="[Header]\r\n" />
  57:          <param name="Footer" value="[Footer]\r\n" />
  58:          <param name="ConversionPattern" value="%d [%t] %-5p %m%n" />
  59:        </layout>
  60:      </appender>
  61:      <root>
  62:        <level value="DEBUG" />
  63:        <appender-ref ref="CustomAdoNetAppender" />
  64:        <appender-ref ref="ConsoleAppender" />
  65:      </root>
  66:    </log4net>

You can see on line 2 that we specified our new CustomAdoNetAppender as the name and pointed the type to MyCustomNamespace.CustomAdoNetAppender.  This tells Log4Net what class to use and where to find it.

Now you have a Custom AdoNetAppender that gets the database connection from your application settings at run-time.

Organizing a SharePoint Event: What You Need To Know

Mark Rackley, The SharePoint Hillbilly, not only put on a great SharePoint Saturday Ozarks event, but has written a blog post to let everyone know what you should consider if you are thinking about putting on an event like this.  The great thing is that what he discusses could apply to any regional event.

He has great advice on recruiting speakers, sponsors, selecting the venue, website, and day of venue organization.

Mark thanks for putting on a great event and sharing your experience with the community.

Check out the full article here: Organizing a SharePoint Event: What You Need To Know

Installing the Akismet Extension for BlogEngine.NET

In my previous post I mentioned I install the BlogEngine.net Akisment Extension written by Justin Etheredge.  Today Justin Chase, a member of the Microsoft Expression team, has posted great step by step instructions showing how to get it, install it, get a WordPress API key, and configure it.

Resource: Installing the Akismet Extension for BlogEngine.NET by Justin Chase

Blog Updates: Akismet and skribit

Akismet: Comment Spam filtering

akismet_blackbox

Recently I have been getting unwanted spam comments to my blog post, so I went looking for an Akismet extension for BlogEngine.  When I had a WordPress blog it was there by default you just had to get a API Key form WordPress.  It works by checking comments against a centeralized black list, if it is ok the comment goes through, if not, squash!!!! I love it. 

Thankfully Justin Etheredge created the BlogEngine.net Akisment Extension, I highly recommend you make this addition to your blog to stop unwanted comments.

skribit: Blog Idea suggestion service

skribit

Added a new service to the blog called skribit, it is very similar to user voice, it allows you to suggest topics you would like to see blogged about.  So if you have an idea of something you would like to see covered in this blog give it a try.

Adding it to BlogEngine was a snap, just used the skribit widget creator and then copied the generated code and added it in the Settings page of you BlogEngine admin, scroll to the bottom and paste the widget code into the HTML head section. Voila, you are done!

User Group Radio: Zach Young talks about using Live Meeting

My good friend Zach Young has been doing a lot of great work with using Live Meeting to enhance the user group and event experience over the last year.  He has even been part of the Virtual Alt .Net (VAN) calls that have grown like crazy and are completely virtual! 

I had the chance to corner him the other night after our Arkansas User Group Leadership call and interview him on the subject for User Group Radio, so head on over and check out this great interview and the awesome resources Zach has put together to make getting off the ground with Live Meeting a lot easier on the rest of us!

Zach thanks for the interview it was a great time.

Calendar

<<  May 2024  >>
MonTueWedThuFriSatSun
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

View posts in large calendar

Widget Category list not found.

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))X

Tag cloud

    Widget Month List not found.

    Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))X

    Widget AuthorList not found.

    Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))X

    Widget TextBox not found.

    Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))X