NLog - 将NULL写入可选数据库列

cwe*_*ton 9 .net c# asp.net logging nlog

我正在使用NLog登录ASP.Net应用程序并使用Microsoft Sql Server的数据库目标.

我有一些可选的记录参数,并不总是指定.我希望这些在没有提供时写为null,但是NLog似乎总是把它们写成空字符串.

有没有办法将其配置为将null写为默认值?

参考:https://github.com/nlog/NLog/wiki/Database-target

Fer*_*ero 12

这是一个老问题,但由于给出的解决方案有点' hacky '我想给自己的,我认为它比db过程更简单,使用案例更优雅.

您可以尝试使用NULLIF比较2个表达式的函数编写NULL,如果它们相等则返回NULL,否则返回第一个表达式(msdn NULLIF页面).

这样,NLog配置文件中的commandText看起来像:

INSERT INTO [dbo].[log] ([message], [optional]) 
VALUES (@message, NULLIF(@optional, ''))
Run Code Online (Sandbox Code Playgroud)


kol*_*sov 7

NLog使用StringBuilder来创建参数值.即使未指定参数,它也会将值初始化为builder.ToString(),这是一个空字符串.

您可以像这样更改commandText:

INSERT INTO [dbo].[log] ([message], [optional]) 
VALUES 
(
    @message, 
    case 
      when len(@optional) = 0 then null 
      else @optional 
    end
)
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎是一个黑客.我希望有更好的解决方案.


Rol*_*sen 7

NLog版本。4.7.4 添加了参数选项AllowDbNull,因此您可以这样做:

<parameter name="@exception" layout="${exception:format=tostring}" allowDbNull="true" />
<parameter name="@correlationid" layout="${activityid}" dbType="DbType.Guid" allowDbNull="true" />
Run Code Online (Sandbox Code Playgroud)

当 时,Nlog 会自动将空字符串/无输出转换为 DbNull-value allowDbNull="true"


wag*_*ghe 2

[编辑]

也许比我下面建议的更明显的解决方案是从使用 INSERT 语句更改为使用数据库过程来记录。如果您使用数据库过程,那么您可以自己处理从空字符串到 null 的混合。我不确定您是否可以将数据库过程与 NLog 的数据库目标一起使用。Log4net 支持它,所以我猜测 NLog 也支持它。

这是一个示例(在链接问题的答案中),我发现有人使用 NLog 使用存储过程登录数据库的配置。

http://nlog-forum.1685105.n2.nabble.com/Using-a-stored-procedure-for-the-DB-Target-td2621725.html

我在这里看到:

http://nlog.codeplex.com/workitem/5418

抱怨它不起作用(至少在 NLog 2.0 beta 中)。

这两个示例之间的区别之一是工作示例使用“exec LoggingProcedureName ...”,而非工作示例使用“LoggingProcedureName ...”

希望这可以帮助。

[编辑结束]

我无法评论为什么 NLog 写入空字符串而不是 null 或如何使 NLog 写入 null 而不是空字符串,但我想知道您是否可以通过额外的配置使这项工作按照您想要的方式进行?

日志记录参数什么时候是可选的?您的代码中是否有某些位置始终记录某些值,而其他位置则从不记录某些值?您(作为开发人员)能否知道哪些可选参数适用于应用程序的哪些部分?

您能否配置多个数据库目标,每个目标都指定“正确”的参数?然后,您可以将记录器指向适合代码位置的特定数据库目标。

假设您的应用程序(按名称空间)划分为(通常)在“之前”、“期间”和“之后”执行的代码。

在“之前”代码中,您可能正在记录参数 A。在“期间”代码中,您可能正在记录参数 B。在“之后”代码中,您可能正在记录参数 C。因此,您的日志记录表可能包含列喜欢:

DateTime, Logger, LogLevel, A, B, C, Message, Exception
Run Code Online (Sandbox Code Playgroud)

现在,您有一个数据库目标,它为每个日志记录语句插入所有这些值。

如果您有三个插入值的数据库目标,如下所示:

DataTime, Logger, LogLevel, A, Message, Exception
DataTime, Logger, LogLevel, B, Message, Exception
DataTime, Logger, LogLevel, C, Message, Exception
Run Code Online (Sandbox Code Playgroud)

您可以像这样配置您的部分:

  <rules>
    <logger name="Before.*" minlevel="Trace" writeTo="databaseA" />
    <logger name="During.*" minlevel="Trace" writeTo="databaseB" />
    <logger name="After.*" minlevel="Trace" writeTo="databaseC" />
  </rules>
Run Code Online (Sandbox Code Playgroud)

显然,这个想法可能存在几个问题:

  1. 可能(或容易)划分记录器以匹配参数的“可选性”。

  2. 可选参数的组合可能太多,无法实现这一点(可能与 1 具有相同的缺点)。

  3. 一次让数据库目标的日志处于活动状态可能不是一个好主意。也许这会导致性能问题。

嗯,这就是我所拥有的一切。我不知道我的想法是否可行,更不用说它是否实用了。

也许更好的解决方案是 NLog 允许每个数据库参数有一个额外的属性,允许您说“发送 null 而不是空字符串”。

我想我应该建议您也可能想在NLog 论坛中提出这个问题。今天早些时候,该论坛上的“Craig”提出了相同(或类似)的问题。也许你是克雷格。