Использование uniqueidentifiers / guids в качестве пользовательских свойств в log4net
-
05-07-2019 - |
Вопрос
Я пытаюсь добавить пользовательское свойство, которое является guid, но оно выдает мне эту ошибку:
System.InvalidCastException: не удалось преобразовать значение параметра из строки гиду. --- & GT; System.InvalidCastException: Invalid приведение от 'System.String' к 'System.Guid'.
Я указываю это в конфиге:
<parameter>
<parameterName value="@id" />
<dbType value="Guid" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%X{id}" />
</layout>
</parameter>
Фактический код (фрагмент), который я использую, таков:
Guid guid = Guid.NewGuid();
if (defaultLogger.IsEnabledFor(level))
{
var loggingEvent = new LoggingEvent(ThisDeclaringType,
defaultLogger.Repository, defaultLogger.Name, level, message, exception);
loggingEvent.Properties["Id"] = guid;
Помогите, пожалуйста? :) Поле id в базе данных определено как уникальный идентификатор NOT NULL, но оно не имеет противопоказаний для первичного ключа.
Решение
Для вашего примера должно работать следующее:
<parameter>
<parameterName value="@Oid" />
<dbType value="Guid" />
<layout type="log4net.Layout.RawPropertyLayout">
<key value="Id" />
</layout>
</parameter>
Важно, чтобы вы переименовали @id во что-то другое, иначе вы получите нулевые значения в базе данных, даже если попытаетесь вставить строки,
А затем используйте RawPropertyLayout для хранения, поскольку вам не нужно делать преобразование.
Другие советы
1. Загрузите исходный код log4.net
2. Измените функцию FormatValue
внутри файла log4net.Appender.AdoNetAppender.cs
следующим образом:
virtual public void FormatValue(IDbCommand command, LoggingEvent loggingEvent)
{
// Lookup the parameter
IDbDataParameter param = (IDbDataParameter)command.Parameters[m_parameterName];
// Format the value
object formattedValue = Layout.Format(loggingEvent);
// If the value is null then convert to a DBNull
if (formattedValue == null)
{
formattedValue = DBNull.Value;
}
if (param.DbType == System.Data.DbType.Guid)
{
param.Value = new Guid(formattedValue.ToString());
}
else
{
param.Value = formattedValue;
}
}
тогда это работает!
Если вы хотите получить универсальное свойство GUID, вы можете сделать следующее:
private void ConfigureLog4Net()
{
// adds a global custom log4net property
log4net.GlobalContext.Properties[nameof(Guid.NewGuid)] = new NewGuidWrapper();
// configures log4net by XML configurations from a .config file
log4net.Config.XmlConfigurator.Configure();
}
private class NewGuidWrapper
{
// will return new GUID every time it's called
public override string ToString() => Guid.NewGuid().ToString();
}
и затем вы можете вызвать свойство следующим образом:
<layout type="log4net.Layout.PatternLayout">
<!-- if you want to format the layout as a GUID followed by a message -->
<conversionPattern value="%property{NewGuid} %m%n" />
</layout>
Вы также можете использовать макет такого типа для настраиваемого параметра БД, как описано здесь .