Использование различных ConnectionString в пользовательском AdoNetAppender с log4net
Я хочу использовать 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 в зависимости от некоторых переменных. Свойство ConnectionString, которое я добавляю в свой пользовательский appender, просто никогда не вызывается. Есть идеи, где я что-то упускаю?
2 ответа
Какую версию log4net вы используете?
В любом случае, new
Свойство ConnectionString в вашем производном классе не будет вызываться автоматически из существующей инфраструктуры.
Вы можете добиться большего успеха, переопределив подходящий виртуальный элемент: например, если вы используете log4net 1.2.11, вы можете переопределить CreateConnection
или же ResolveConnectionString
метод.
ОБНОВЛЕНИЕ в ответ на комментарий:
Но CreateConnection используется только один раз, поэтому я не могу использовать один и тот же appender для нескольких ConnectionString
Да, лог4нет AdoNetAppender
имеет необычный дизайн, в котором объект соединения остается открытым и повторно используется для каждого запроса на регистрацию. В отличие от обычного рекомендуемого подхода, который заключается в создании / открытии соединения БД как можно позже и закрытии его сразу после использования. Рекомендуемый подход позволяет приложению использовать преимущества встроенного пула соединений ADO.NET.
Одна вещь, которую вы могли бы попробовать, может быть переопределить SendBuffer(LoggingEvent[] events)
и в вашем переопределении вызовите базовый класс, а затем закройте соединение. Это заставит соединение открываться каждый раз SendBuffer
называется.
Хотя я не уверен, что это даст вам все, что вы хотите - вы говорите о приложении Multitenant, использующем несколько строк подключения. В этом случае массив LoggingEvent
перешел к SendBuffer
может содержать события, которые должны быть отправлены на разные соединения. Возможно, вам нужно будет использовать какой-то атрибут LoggingEvent
разделить входной массив по целевому соединению, затем для каждого целевого соединения открыть соединение, вызвать base.SendBuffer
затем закройте соединение.
Это будет работать на существующем 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 будет жаловаться на конфигурацию, что значение строки подключения не было задано, но это не имеет значения, и вы, вероятно, в любом случае не заметите, если не включите разрыв всех исключений.