问题
I'm trying to add a custom property which is a guid, but it gives me this error:
System.InvalidCastException: Failed to convert parameter value from a String to a Guid. ---> System.InvalidCastException: Invalid cast from 'System.String' to 'System.Guid'.
I specify this in the config:
<parameter>
<parameterName value="@id" />
<dbType value="Guid" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%X{id}" />
</layout>
</parameter>
The actual code (snippet) i use is this:
Guid guid = Guid.NewGuid();
if (defaultLogger.IsEnabledFor(level))
{
var loggingEvent = new LoggingEvent(ThisDeclaringType,
defaultLogger.Repository, defaultLogger.Name, level, message, exception);
loggingEvent.Properties["Id"] = guid;
Any help please? :) The id field in the database is defined as a uniqueidentifier NOT NULL, but it does not have the primary key contraint.
回答1:
For your example the following should work:
<parameter>
<parameterName value="@Oid" />
<dbType value="Guid" />
<layout type="log4net.Layout.RawPropertyLayout">
<key value="Id" />
</layout>
</parameter>
Important is you rename @id to something else otherwise you will get Null values in database even if you try to insert strings,
And then use RawPropertyLayout to store, cus you do not need to do a convertion.
回答2:
1. Download the source code of log4.net
2. Change the function FormatValue
inside the file log4net.Appender.AdoNetAppender.cs
like this:
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;
}
}
then it works!
回答3:
If you want to get a general-purpose GUID property, you can do the following:
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();
}
and then you can call the property in the following way:
<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>
You can also use such type of layout for a custom DB parameter as it's described here.
来源:https://stackoverflow.com/questions/424018/using-uniqueidentifiers-guids-as-custom-properties-in-log4net