在自定义AdoNetAppender中使用log4net使用不同的ConnectionString

时间:2015-01-28 21:29:05

标签: c# log4net adonetappender

我想使用我将在运行时定义的ConnectionString。我找到了很多例子,但我无法使它发挥作用。

我创建了一个自定义AdoNetAppender:

 public class AdoNetMultiTenantAppender : AdoNetAppender
{
    public new string ConnectionString
    {
        get
        {
            return base.ConnectionString;
        }

        set
        {
            base.ConnectionString = Tenant.Current.DataSource.ConnectionString; // Return the connection string
        }
    }
}

我有以下配置:

<appender name="AdoNetMultiTenantAppender" type="MyNameSpace.AdoNetMultiTenantAppender">
    <bufferSize value="1" />
    <connectionstring value="" />
    <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    <commandText value="[...]" />
    <parameter>
        [...]
    </parameter>
</appender>

我的记录器在配置文件中定义如下:

  <logger name="ProcessLogger" additivity="false">
    <level value="INFO"/>
    <appender-ref ref="AdoNetMultiTenantAppender"/>
  </logger>

最后,为了让我的Logger得到我正在做的代码:

[...]    
private static readonly ILog Logger = LogManager.GetLogger("ProcessLogger");
[...]
ProcessLogger.Logger.Info(message);
[...]

当我试图将连接字符串“硬编码”到我的配置中时,它正在工作。但我不能这样做因为我需要一个不同的ConnectionString,具体取决于一些变量。我放在自定义appender中的属性ConnectionString永远不会调用。知道我错过了什么吗?

2 个答案:

答案 0 :(得分:2)

您使用的是什么版本的log4net?

在任何情况下,派生类中的new ConnectionString属性都不会从现有基础结构中自动调用。

您可以通过覆盖合适的虚拟成员获得更多成功:例如,如果您使用的是log4net 1.2.11,则可以覆盖CreateConnectionResolveConnectionString方法。

更新发表评论:

  

但是CreateConnection只使用了一次,所以我不能为多个ConnectionString使用相同的appender

是的,log4net AdoNetAppender有一个不寻常的设计,因为连接对象保持打开状态并重复用于每个日志记录请求。与通常推荐的方法形成对比,即尽可能晚地创建/打开数据库连接,并在使用后立即关闭它。推荐的方法允许应用程序利用ADO.NET的内置连接池。

您可以尝试的一件事可能是覆盖SendBuffer(LoggingEvent[] events),并在您的覆盖调用基类中然后关闭连接。这将强制每次调用SendBuffer时重新打开连接。

我不确定这是否会为您提供所需的一切 - 您谈到使用多个连接字符串的Multitenant应用程序。在这种情况下,传递给LoggingEvent的{​​{1}}数组可能包含应发送到不同连接的事件。也许您需要使用SendBuffer的某个属性来通过目标连接拆分输入数组,然后对于每个目标连接,打开连接,调用LoggingEvent然后关闭连接。

答案 1 :(得分:1)

这适用于现有的AdoNetAppender:

public static void SetConnectionString(string connectionString)
{
    Hierarchy logHierarchy = log4net.LogManager.GetRepository() as Hierarchy;

    if (logHierarchy == null)
    {
        throw new InvalidOperationException("Can't set connection string as hierarchy is null. Has logging been initialised?");
    }

    // Assumes there is only one appender to be configured
    var appender = logHierarchy.GetAppenders().OfType<AdoNetAppender>().SingleOrDefault();

    if (appender == null)
    {
        throw new InvalidOperationException("Can't set connection string as can't locate a database appender");
    }

    appender.ConnectionString = connectionString;
    appender.ActivateOptions();
}

请注意,AdoNetAppender会抱怨配置中没有设置连接字符串值,但这并不重要,除非您打开所有例外,否则您可能无法注意到。< / p>

相关问题