Using uniqueidentifiers/guids as custom properties in log4net

匆匆过客 提交于 2020-02-01 17:40:57

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!