Log4net使用自定义appender将自定义对象写入sql数据库?

时间:2016-02-10 18:52:19

标签: sql-server-2012 log4net

在这里使用SQL Server 2012是我的表:

CREATE TABLE [dbo].[Test]
(
    [One] [VARCHAR](50) NOT NULL,
    [Two] [VARCHAR](50) NOT NULL
) ON [PRIMARY]

这是我的追随者:

<appender name="TestAppender" type="log4net.Appender.AdoNetAppender">
    <bufferSize value="1" />
    <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    <connectionString value="data source=localhost;initial catalog=ApplicationLog;integrated security=false;persist security info=True;User ID=someUser;Password=somePassword" />
    <commandText value="INSERT INTO [dbo].[Test] ([One],[Two]) VALUES (@one, @two)" />
    <parameter>
        <parameterName value="@one"/>
        <dbType value="String"/>
        <size value="50"/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%one"/>
        </layout>
    </parameter>
    <parameter>
        <parameterName value="@two"/>
        <dbType value="String"/>
        <size value="50"/>
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%two"/>
        </layout>
    </parameter>
</appender>

以下是我如何在代码中获取记录器的实例并尝试写入它:

private static readonly ILog TestLogger = LogManager.GetLogger("TestAppender");
TestLogger.Info(new Test {One = "someOne", Two = "someTwo"});

这是我的测试类:

public class Test
{
    public string One { get; set; }
    public string Two { get; set; }
}

在单步执行此操作后,我的表中有一条记录,列的内容为:

One: "one" Two: "12wo"

到底是什么&#34; 12wo&#34;?我知道我在这里遗漏了一些东西。我认为我的转换模式是错误的。我试过这个:

<conversionPattern value="%property{one}"/>

..但这也不起作用。我是否必须编写自定义图案布局或其他内容?感谢。

1 个答案:

答案 0 :(得分:2)

This site指出了我正确的方向。

我必须创建一个自定义LayoutPattern和PatternConverter才能成功地将我的对象写入日志。原来我在数据库中得到的奇怪的“12wo”文本是因为转换模式使用printf c样式语法。无论如何,这里有一些代码。

public class TestLayoutPattern : PatternLayout
{
    public TestLayoutPattern()
    {
        AddConverter(new ConverterInfo
        {
            Name = "test",
            Type = typeof (TestConverter)
        });
    }
}
public class TestConverter : PatternConverter
{
    protected override void Convert(System.IO.TextWriter writer, object state)
    {
        if (state == null)
        {
            writer.Write(SystemInfo.NullText);
            return;
        }

        var loggingEvent = state as LoggingEvent;
        if (loggingEvent == null)
            throw new NullReferenceException("loggingEvent");

        var test = loggingEvent.MessageObject as Test;

        if (test == null)
        {
            writer.Write(SystemInfo.NullText);
        }
        else
        {
            switch (Option.ToLower())
            {
                case "one":
                    writer.Write(test.One);
                    break;
                case "two":
                    writer.Write(test.Two);
                    break;                    
                default:
                    writer.Write(SystemInfo.NullText);
                    break;
            }
        }
    }
}

以下是如何按名称获取记录器的实例:

private static readonly ILog TestLogger = LogManager.GetLogger("TestLogger");

以下是如何将Test对象写入日志。

TestLogger.Info(new Test {One = "field one", Two = "field two"});

以下是如何在web.config中定义参数。

<parameter>
  <parameterName value="@one" />
  <dbType value="String" />
  <size value="50" />
  <layout type="MyApp.TestLayoutPattern">
    <conversionPattern value="%test{one}" />
  </layout>
</parameter>

需要注意的另一件事是web.config的root和logger部分。在根部分中,定义了默认记录器的级别设置。我可以在记录器部分中定义我的自定义TestLogger,它将引用appender,如下所示。这允许我按名称访问TestLogger,如上所示。

<root>
  <level value="ALL"/>
  <appender-ref ref="ADONetAppender"/>
</root>
<logger additivity="false" name="TestLogger">
  <level value="ALL"/>
  <appender-ref ref="TestAppender" />
</logger>

我还发现如果你只想在默认的ADONetAppender中添加一些属性(并在表中添加几个字段),你可以改为使用log4net.ThreadContext来设置这些属性:

log4net.ThreadContext.Properties["MyCustomPrperty"] = value;

然后在参数部分下的web.config中,您可以像这样访问该属性:

<parameter>
  <parameterName value="@myCustomProperty"/>
  <dbType value="String"/>
  <layout type="log4net.Layout.RawPropertyLayout">
    <key value="MyCustomProperty" />
  </layout>
</parameter>