在log4net中使用唯一标识符/全局唯一标识符(uniqueidentifiers/guids)作为自定义属性

10

我想要添加一个自定义属性,该属性是GUID类型,但是它给了我这个错误:

System.InvalidCastException: 无法将参数值从字符串转换为Guid。 ---> System.InvalidCastException: 从'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字段被定义为uniqueidentifier NOT NULL,但它没有主键约束。


你为什么想要一个GUID?这是为了提供某种上下文吗? - Mitch Wheat
3个回答

25

对于你的示例,以下代码应该有效:

<parameter>
<parameterName value="@Oid" />
<dbType value="Guid" />
<layout type="log4net.Layout.RawPropertyLayout">
<key value="Id" />
</layout>
</parameter>

重要的是你将@id重命名为其他名称,否则即使尝试插入字符串,数据库也会获得空值。

然后使用RawPropertyLayout来存储,因为你不需要进行转换。


3
为了清晰起见,<key>是在LoggingEvent属性集合中查找值的名称。 - bluedot

0

1. 下载 log4.net 的源代码

2. 修改文件 log4net.Appender.AdoNetAppender.cs 内的函数FormatValue,修改如下:

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;
            }
        }

然后它就可以工作了!


0
如果您想获取通用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>

您还可以使用此类型的布局来自定义DB参数,如此处所述。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接