2016-02-10 68 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>