【问题标题】:Log4net, ADONetAppender and Stored Procedure: Set Precision & Scale?Log4net、ADONetAppender 和存储过程:设置精度和规模?
【发布时间】:2014-07-01 11:25:44
【问题描述】:

我认为的一些小事情正在像我预期的那样阻止我的应用程序进行数据库日志记录。

  • 文本命令有效。 INSERTEXEC 命令都可以工作,并且数据会输入到数据库中
  • 如果我取消注释 ExecutionTime 参数,它就会停止工作。,我知道在某个时候它正在工作,但我无法弄清楚为什么取消注释参数,更不用说添加它,会导致 Appender 失败默默地。
    • 现在调试工作发现错误。下面列出并更新了精度和规模。
  • 我正在尝试启用内部调试,但它似乎不想工作。找到了问题。将配置部分移动到正确的位置(不在 log4net 下)。
  • 如果我将 commandType 切换为 StoredProcedure,它就会停止工作,即使文本版本也能工作
    • 仍然是个问题。尝试不同的事情,但运气不佳

SQL:

DROP TABLE [LOG];
GO
CREATE TABLE [dbo].[LOG] (
     [Id] [int] IDENTITY(1,1) NOT NULL
    ,[Origin] [varchar](55) null
    ,[LogDate] [datetime] NOT NULL
    ,[Thread] [varchar](32) NOT NULL
    ,[Context] [varchar](10) NOT NULL
    ,[Level] [varchar](10) NOT NULL
    ,[Logger] [varchar](255) NOT NULL
    ,[Message] [varchar](4000) Not NULL
    ,[MethodName] [varchar](200) NULL
    ,[Parameters] [varchar](4000) NULL
    ,[Exception] [varchar](4000) NULL
    ,[ExecutionTime] [decimal](14, 4) NULL
)
GO

DROP PROCEDURE InsertLog
GO
CREATE PROCEDURE [dbo].[InsertLog]
     @LogDate DateTime
    ,@Thread varchar(32)
    ,@Context varchar(10)
    ,@Level varchar(10)
    ,@Logger varchar(255)
    ,@Message varchar(4000)
    ,@MethodName varchar(200) = null
    ,@Parameters varchar(4000) = null
    ,@Exception varchar(4000) = null
    ,@ExecutionTime decimal(14,4) = null
AS
BEGIN
    SET NOCOUNT ON;

    INSERT INTO [dbo].[LOG] ([Origin],[LogDate],[Thread],[Level],[Logger],[Message],[MethodName],[Parameters],[Exception],[Context]) 
    VALUES ('InsertLog',@LogDate, @Thread, @Level, @Logger, @Message, @MethodName, @Parameters, @Exception, @Context)
END
GO

App.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
        ...
    </configSections>
    <connectionStrings>...</connectionStrings>
    <applicationSettings>...</applicationSettings>
    <log4net configSource="Log4Net.config" />
<appSettings>
    <add key="log4net.Internal.Debug" value="true" />
</appSettings>
<system.diagnostics>
    <trace autoflush="true">
        <listeners>
            <add name="textWriterTraceListener" type="System.Diagnostics.TextWriterTraceListener" initializeData=".\log4net.log" />
        </listeners>
    </trace>
</system.diagnostics>
</configuration>

log4net.config

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
    <root>
        <level value="ALL" />
        <!-- ColoredConsoleAppender works, so It's not listed below -->
        <appender-ref ref="ColoredConsoleAppender"/>
        <appender-ref ref="ADONetAppender" />
        <appender-ref ref="OutputDebugStringAppender" />
        <appender-ref ref="TraceAppender" />
    </root>
    <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
        <threshold value="ALL"/>
        <bufferSize value="1" />
        <lossy value="false"/>
        <param name="UseTransactions" value="False" />
        <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
        <connectionString value="..." />
        <!--<commandText value="
            INSERT INTO [Log] ([Origin],[LogDate],[Thread],[Context],[Level],[Logger],[Message],[MethodName],[Parameters],[Exception])
            VALUES ('ADONetAppender',@log_date,@thread,@Context,@Level,@Logger,@Message,@MethodName,@Parameters,@Exception);"
        />-->
        <commandText value="
            exec InsertLog @log_date,@thread,@Context,@Level,@Logger,@Message,@MethodName,@Parameters,@Exception;"
        />
        <!--<commandType value="StoredProcedure" />-->
        <!--<commandText value="InsertLog" />-->
        <parameter name="LogDate">
            <parameterName value="@log_date"/>
            <dbType value="DateTime"/>
            <layout type="log4net.Layout.RawTimeStampLayout"/>
        </parameter>
                    ...
        <!-- This causes appender to fail silently. -->
        <parameter name="ExecutionTime">
            <parameterName value="@ExecutionTime"/>
            <dbType value="Decimal"/>
            <precision value="14"/>
            <scale value="4"/>
            <layout type="log4net.Layout.PatternLayout" value="%property{execution_time}" />
        </parameter>
    </appender>
    <appender name="OutputDebugStringAppender" type="log4net.Appender.OutputDebugStringAppender">
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date %-5level %logger (%file:%line) - %message%newline" />
        </layout>
    </appender>
    <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date %-5level - %message%newline" />
        </layout>
    </appender>
</log4net>

更新 1 现在我的 Trace 正在工作......它抱怨 DB 命令需要明确设置精度和比例。不知道该怎么做,因为我见过的例子都没有设置

log4net:ERROR [AdoNetAppender] 错误代码:GenericFailure。不能 准备数据库命令 [ exec InsertLog @log_date,@thread,@Context,@Level,@Logger,@Message,@MethodName,@Parameters,@Exception; ] System.InvalidOperationException:SqlCommand.Prepare 方法需要 “十进制”类型的参数具有明确设置的精度和 规模。在 System.Data.SqlClient.SqlParameter.Prepare(SqlCommand cmd) 在 System.Data.SqlClient.SqlCommand.Prepare() 在 log4net.Appender.AdoNetAppender.InitializeDatabaseCommand()

更新 2 随着精度/比例的增加,误差会发生变化。它现在抱怨:

log4net:ERROR [AdoNetAppender] 错误代码:GenericFailure。 DoAppend 失败 System.FormatException:无法将参数值从字符串转换为小数。 ---> System.FormatException:输入字符串的格式不正确。

【问题讨论】:

    标签: c# configuration log4net adonetappender


    【解决方案1】:

    AdoNetAppenderParameter 类中有两个参数可以添加到 xml 文件中的 ExecutionTime 参数中,PrecisionScale

    <parameter name="ExecutionTime">
        <parameterName value="@ExecutionTime"/>
        <dbType value="Decimal"/>
        <precision value="14"/>
        <scale value="4"/>
        <layout type="log4net.Layout.PatternLayout" value="%property{execution_time}" />
    </parameter>
    

    【讨论】:

    • 我想尝试一下,但认为它太简单了,找不到一个例子。但这确实让我克服了那个错误并进入“无法将(null) 转换为十进制”区域
    • 没有提及 value="%property{... 的不同文章和 cmets 的数量非常令人沮丧。直到我遇到这个问题,我才发现我的价值观没有更新。谢谢你这么多
    【解决方案2】:
    • 启用调试并发现有关 Precision 和 Scale 的投诉
    • 接下来是 NULL 值。它们被转换成文字 (null) 并且在将其转换为小数时窒息。
    • 将 Log4net.config 转换为 STRING 并在存储过程中添加了一些转换逻辑
    • 将 ExecutionTime 转换为 Int,因为我使用的代码以毫秒为单位。

    SQL:

        DROP TABLE [LOG];
        GO
        CREATE TABLE [dbo].[LOG] (
             [Id] [int] IDENTITY(1,1) NOT NULL
            ,[LogDate] [datetime] NOT NULL
            ,[Thread] [varchar](32) NOT NULL
            ,[Level] [varchar](10) NOT NULL
            ,[Logger] [varchar](255) NOT NULL
            ,[Message] [varchar](4000) NOT NULL
            ,[Exception] [varchar](4000) NULL
            ,[Context] [varchar](10) NULL
            ,[MethodName] [varchar](200) NULL
            ,[Parameters] [varchar](4000) NULL
            ,[ExecutionTime] int NULL
            --,[Origin] [varchar](55) NOT NULL
            --,[ExecutionRaw] [varchar](4000) NULL
        )
        GO
    
        DROP PROCEDURE InsertLog
        GO
        CREATE PROCEDURE [dbo].[InsertLog]
             @LogDate DateTime
            ,@Thread varchar(32)
            ,@Level varchar(10)
            ,@Logger varchar(255)
            ,@Message varchar(4000)
            ,@Exception varchar(4000) = null
            ,@Context varchar(10) = null
            ,@MethodName varchar(200) = null
            ,@Parameters varchar(4000) = null
            ,@ExecutionTime varchar(32) = null
        AS
        BEGIN
            SET NOCOUNT ON;
            --DECLARE @ETChar varchar(32); set @ETChar = @ExecutionTime;
    
            if @Exception     = '' set @Exception = null;
            if @Context       = '(null)' set @Context = null;
            if @MethodName    = '(null)' set @MethodName = null;
            if @Parameters    = '(null)' set @Parameters = null;        
            if @ExecutionTime = '(null)' set @ExecutionTime = null;
    
            DECLARE @ETInt int;          set @ETInt  = convert(int, @ExecutionTime);
    
            INSERT INTO [dbo].[LOG] (
                 [LogDate]
                ,[Thread]
                ,[Level]
                ,[Logger]
                ,[Message]
                ,[Exception]
                ,[Context]
                ,[MethodName]
                ,[Parameters]
                ,[ExecutionTime]
                --,[Origin]
                --,[ExecutionRaw]
                )
            VALUES (
                 @LogDate
                ,@Thread
                ,@Level
                ,@Logger
                ,@Message
                ,@Exception
                ,@Context
                ,@MethodName
                ,@Parameters
                ,@ETInt
                --,'InsertLog'
                --,@ETChar
                )
    
            SET NOCOUNT OFF;
        END
        GO
    
        DROP INDEX [IX_LEVEL] ON [LOG]
        GO
        CREATE NONCLUSTERED INDEX [IX_Level] ON [dbo].[LOG] ( [Level] ASC ); 
        GO
    

    Log4Net.config:

    <?xml version="1.0" encoding="utf-8"?>
    
    <log4net>
      <root>
        <level value="DEBUG" />
        <appender-ref ref="ADONetAppender" />
      </root>
      <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
        <threshold value="ALL" />
        <bufferSize value="1" />
        <lossy value="false" />
        <param name="UseTransactions" value="False" />
        <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
        <connectionString value="..." />
        <commandType value="StoredProcedure" />
        <commandText value="InsertLog" />
        <parameter name="LogDate">
          <parameterName value="@LogDate" />
          <dbType value="DateTime" />
          <layout type="log4net.Layout.RawTimeStampLayout" />
        </parameter>
        <parameter name="Thread">
          <parameterName value="@Thread" />
          <dbType value="String" />
          <size value="32" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%thread" />
          </layout>
        </parameter>
        <parameter name="Level">
          <parameterName value="@Level" />
          <dbType value="String" />
          <size value="10" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%level" />
          </layout>
        </parameter>
        <parameter name="Logger">
          <parameterName value="@Logger" />
          <dbType value="String" />
          <size value="255" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%logger" />
          </layout>
        </parameter>
        <parameter name="Message">
          <parameterName value="@Message" />
          <dbType value="String" />
          <size value="4000" />
          <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%message" />
          </layout>
        </parameter>
        <parameter name="Exception">
          <parameterName value="@Exception" />
          <dbType value="String" />
          <size value="4000" />
          <layout type="log4net.Layout.ExceptionLayout" />
        </parameter>
        <parameter name="Context">
          <parameterName value="@Context" />
          <dbType value="String" />
          <size value="10" />
          <layout type="log4net.Layout.PatternLayout" value="%x" />
        </parameter>
        <parameter name="MethodName">
          <parameterName value="@MethodName" />
          <dbType value="String" />
          <size value="200" />
          <layout type="log4net.Layout.PatternLayout" value="%property{method_name}" />
        </parameter>
        <parameter name="Parameters">
          <parameterName value="@Parameters" />
          <dbType value="String" />
          <size value="4000" />
          <layout type="log4net.Layout.PatternLayout" value="%property{properties}" />
        </parameter>
        <parameter name="ExecutionTime">
          <parameterName value="@ExecutionTime" />
          <dbType value="String" />
          <size value="32" />
          <layout type="log4net.Layout.PatternLayout" value="%property{execution_time}" />
        </parameter>
      </appender>
    </log4net>
    

    【讨论】:

      猜你喜欢
      • 2010-09-12
      • 1970-01-01
      • 2016-05-27
      • 2012-11-23
      • 2015-02-11
      • 1970-01-01
      • 2012-08-08
      • 1970-01-01
      • 2012-04-29
      相关资源
      最近更新 更多