2016-02-10 48 views
1

使用SQL Server 2012,这里是我的表:Log4net使用自定义appender将自定义对象写入sql数据库?

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

这里是我的appender:

<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" 

到底是什么?“12WO”?我知道我在这里错过了一些东西。我认为我的转换模式是错误的。我试过这个:

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

..但那也行不通。我必须编写一个自定义模式布局或什么?谢谢。

回答

1

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"); 

这里是如何写一个测试对象的日志。

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根和记录部分。在根节中,默认记录器是通过其级别来定义的。我可以在记录器部分定义我的自定义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>