log4net AdoNetAppender在将null插入数据库时插入了"Null"字符串

3

我在我的.NET 3.5应用程序中使用了log4net日志记录。 日志记录插入到数据库中。 我遇到的一个问题是,对于我没有设置数据的数据库,它插入了“NULL”而不是数据库的null值。

我的配置如下:

 <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
    <immediateFlush value="true" />
    <bufferSize value="0" />
    <connectionType value="MySql.Data.MySqlClient.MySqlConnection, MySql.Data" />
    <connectionString value="data source=localhost;initial catalog=logging_db;User ID=root;Password=" />
    <commandText value="INSERT INTO system_log(appname, action,context_id)
                 VALUES (@appname, @action, @context_id);" />
    <parameter>
      <parameterName value="appname" />
      <dbType value="String" />
      <size value="10" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="My Web Service" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="action" />
      <dbType value="String" />
      <size value="45" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%5c{1}.%M" />
      </layout>
    </parameter>
  <parameter>
      <parameterName value="context_id" />
      <dbType value="String" />
      <size value="48" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%X{context_id}" />
      </layout>
    </parameter>
    <filter type="log4net.Filter.LevelRangeFilter">
      <acceptOnMatch value="true" />
      <levelMin value="DEBUG" />
      <levelMax value="FATAL" />
    </filter>
  </appender>

在我的某些方法中,我会将context_id设置为:
log4net.LogicalThreadContext.Properties["context_id"] = "My context";

在我设置的地方插入正常,但在我没有设置的地方插入错误。 我还在https://issues.apache.org/jira/browse/LOG4NET-28上检查了该问题,但那里标记为已解决。

3个回答

4
您可以修改INSERT INTO语句,检查是否为“NULL”字符串并将其替换为DB nulls,灵感来自于这里
因此,它会像这样:
INSERT INTO system_log(appname, action,context_id) VALUES (@appname, @action, CASE WHEN @context_id = 'NULL' THEN NULL ELSE @context_id END );"

更新

如果要使用存储过程,只需将您的语句替换为以下内容:

exec YourStoredProcedure @appname, @action, @context_id

如果没有其他解决方案,那就是我最不想要的。有没有想法可以配置存储过程来代替插入语句? - Kamran Shahid
@KamranShahid 没问题 - 我更新了答案以调用存储过程。 - Peter Szekeli

1

针对这种情况,我更喜欢使用触发器。可以使用ON INSERT或INSTEAD OF INSERT(请参阅https://technet.microsoft.com/zh-cn/library/ms175089(v=sql.105).aspx)。

我的做法是:

CREATE TRIGGER dbo.log_onInsert 
   ON  system_log
   INSTEAD OF INSERT
 AS 
BEGIN
SET NOCOUNT ON;

INSERT INTO system_log(appname, action,context_id)
select 
    appname, action,
    case when inserted.context_id='(null)' then null else inserted.context_id end
from inserted

END
GO

1
Szeki的答案是其中一种解决方案,我的是另一种。编程很少或从来没有一种解决问题的方法。这并不会引起贬低评价的动机。 - David aOll
我同意你的想法。但是根据我12年以上的经验,对于任何情况都不建议使用触发器。你的解决方案将成为一个巨大的性能瓶颈。 - Kamran Shahid

0

请尝试以下操作:

<layout type="log4net.Layout.RawPropertyLayout">
<key value="yourParameterName" />
</layout>

改为:

<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="yourParameterName" />
</layout>

至少在我的情况下,它有所帮助,log4net将NULL值插入到列中


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