2014/09/24

[C#] Dynamic change log4net connectionString

因為遇到資料庫連線字串是要從另一個系統取得, 所以研究了一下 log4net 如何動態設定資料庫連線.

  1. 撰寫一個繼承log4net.Appender.AdoNetAppender的class(ex: MyAdoNetAppender), 程式碼如下:
    public class MyAdoNetAppender : AdoNetAppender
    {
      public new string ConnectionString
      {
        get
        {
          return base.ConnectionString;
        }
        set
        {
          base.ConnectionString = value;
        }
      }
    }
    *這邊有兩點要注意:
    A. 使用了new修飾詞隱藏base的ConnectionString.
    B. ConnectionString要注意大小寫.
  2. 設定log4net的config檔:
    <appender name="AdoNetAppender" type="MVC5WebApplication.Models.MyAdoNetAppender">
      <bufferSize value="1" />
      <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=4.0.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089" />
      <connectionString value="" />
      <commandText value="{insert statement}" />
    </appender>
    
    <connectionString>這個標籤一定要存在; 如果是程式另外會給connectionString值, 這邊的value可以先隨便給.
  3. 當程式開始執行時, MyAdoNetAppender的ConnectionString會先被呼叫到, 所以可以修改第一步的ConnectionString setter, 讓ConnectionString有預設值.
    public class MyAdoNetAppender : AdoNetAppender
    {
      public new string ConnectionString
      {
        get
        {
          return base.ConnectionString;
        }
        set
        {
          if (string.IsNullOrWhiteSpace(value))
          {
            // 如果未給value, 設定預設的ConnectionString
            base.ConnectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
          }
          else
          {
            base.ConnectionString = value;
          }
        }
      }
    }
  4. 最後是動態設定ConnectionString的部分, 我們需要增加一個LogManager來做這件事. 我的MyLogManager Sample Code如下:
    public class MyLogManager
    {
      public static void SetIBatisNetAdoConnectionString(string connectionString)
      {
        ILog logIBatis = LogManager.GetLogger(typeof(IBatisNet.Common.Logging.Impl.Log4NetLoggerFA));
        if (logIBatis != null)
        {
          var appenders = logIBatis.Logger.Repository.GetAppenders().OfType<MyAdoNetAppender>();
          foreach (var appender in appenders)
          {
            appender.ConnectionString = connectionString;
            appender.ActivateOptions();
          }
        }
      }
    }
    
    其中, 因為我主要是為了IBatisNet套件中的Log4NetLoggerFA類別, 設定其ConnectionString, 所以可以看到在GetLogger的部分是針對Log4NetLoggerFA類別做查詢. 接著再針對其下的appenders, 修改其ConnectionString屬性. 最後修改完要記得呼叫ActivateOptions(), 讓更新生效.
  5. 後續程式要更換ConnectionString時, 只要使用以下的Sample Code就可以了.
    MyLogManager.SetIBatisNetAdoConnectionString(Dynamic_ConnectionString);
    

沒有留言: