0

我想使用我将在运行时定义的 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>

最后,为了让我的记录器记录我正在做的代码:

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

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

4

2 回答 2

2

你用的是什么版本的 log4net?

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

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

更新以回应评论:

但是 CreateConnection 只使用一次,所以我不能对多个 ConnectionString 使用同一个 appender

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

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

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

于 2015-01-28T22:21:28.693 回答
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 将在配置中抱怨连接字符串值尚未设置,但这并不重要,除非您打开所有异常的中断,否则您可能不会注意到。

于 2015-01-28T23:52:50.267 回答