log4net配置SqLite代码中

4

今天早些时候,我提出了一个有关从代码配置log4net的问题,并很快得到了答案,这使我能够将其配置为输出到文本文件。自那以后,我的需求发生了变化,我需要使用SqLite作为附加程序。因此,我创建了以下类以允许此操作:

public static class SqLiteAppender
{
    public static IAppender GetSqliteAppender(string dbFilename)
    {
        var dbFile = new FileInfo(dbFilename);

    if (!dbFile.Exists)
    {
        CreateLogDb(dbFile);
    }

    var appender = new AdoNetAppender
                       {
                           ConnectionType = "System.Data.SQLite.SQLiteConnection, System.Data.SQLite",
                           ConnectionString = String.Format("Data Source={0};Version=3;", dbFilename),
                           CommandText = "INSERT INTO Log (Date, Level, Logger, Message) VALUES (@Date, @Level, @Logger, @Message)"
                       };

    appender.AddParameter(new AdoNetAppenderParameter
                              {
                                  ParameterName = "@Date",
                                  DbType = DbType.DateTime,
                                  Layout = new log4net.Layout.RawTimeStampLayout()

                              });

    appender.AddParameter(new AdoNetAppenderParameter
                              {
                                  ParameterName = "@Level",
                                  DbType = DbType.String,
                                  Layout = new log4net.Layout.RawPropertyLayout { Key = "Level" }
                              });

    appender.AddParameter(new AdoNetAppenderParameter
                              {
                                  ParameterName = "@Logger",
                                  DbType = DbType.String,
                                  Layout = new log4net.Layout.RawPropertyLayout { Key = "LoggerName" }
                              });

    appender.AddParameter(new AdoNetAppenderParameter
                              {
                                  ParameterName = "@Message",
                                  DbType = DbType.String,
                                  Layout = new log4net.Layout.RawPropertyLayout { Key = "RenderedMessage" }
                              });

    appender.BufferSize = 100;
    appender.ActivateOptions();
    return appender;
}

public static void CreateLogDb(FileInfo file)
{
    using (var conn = new SQLiteConnection())
    {
        conn.ConnectionString = string.Format("Data Source={0};New=True;Compress=True;Synchronous=Off", file.FullName);
        conn.Open();
        var cmd = conn.CreateCommand();

        cmd.CommandText =
                         @"CREATE TABLE Log(
                            LogId     INTEGER PRIMARY KEY,
                            Date      DATETIME NOT NULL,
                            Level     VARCHAR(50) NOT NULL,
                            Logger    VARCHAR(255) NOT NULL,
                            Message   TEXT DEFAULT NULL
                        );";

        cmd.ExecuteNonQuery();
        cmd.Dispose();
        conn.Close();
    }
}

问题在于,虽然数据库已创建并添加了表,但我没有得到任何关于此的日志记录。

该类的使用方式如下:

BasicConfigurator.Configure(SqLiteAppender.GetSqliteAppender(applicationContext.GetLogFile().FullName));

任何能够指引我朝正确方向前进的帮助,将不胜感激。
谢谢。

您可以查看此问题以获取解决方案:https://dev59.com/k0bRa4cB1Zd3GeqPwg3x - Dillie-O
@Dillie-O - 除了那个问题使用 XML,当 Richard 寻找代码配置时。 - John Farrell
2个回答

6
问题出在 RawPropertyLayout 实例上。在我的测试中,它们没有像预期的那样提取 LevelLoggerName 属性,导致数据库中出现了空约束冲突。可以通过使用以下方式的 PatternLayout 来解决这些问题:
Layout = new Layout2RawLayoutAdapter(new PatternLayout("%level"))

并且

Layout = new Layout2RawLayoutAdapter(new PatternLayout("%logger"))

这是一个完整的工作示例:
using System;
using System.Data;
using System.Data.SQLite;
using System.IO;
using log4net;
using log4net.Appender;
using log4net.Config;
using log4net.Layout;

namespace ConsoleApplication1
{
    class SQLiteLogging
    {
        public static void Test()
        {
            BasicConfigurator.Configure(SqLiteAppender.GetSqliteAppender("D:/test.dat"));
            LogManager.GetLogger(typeof (SqLiteAppender)).Info("Hello there");
        }

        public static class SqLiteAppender
        {
            public static IAppender GetSqliteAppender(string dbFilename)
            {
                var dbFile = new FileInfo(dbFilename);

                if (!dbFile.Exists)
                {
                    CreateLogDb(dbFile);
                }

                var appender = new AdoNetAppender
                                   {
                                       ConnectionType = "System.Data.SQLite.SQLiteConnection, System.Data.SQLite",
                                       ConnectionString = String.Format("Data Source={0};Version=3;", dbFilename),
                                       CommandText = "INSERT INTO Log (Date, Level, Logger, Message) VALUES (@Date, @Level, @Logger, @Message)"
                                   };

                appender.AddParameter(new AdoNetAppenderParameter
                                          {
                                              ParameterName = "@Date",
                                              DbType = DbType.DateTime,
                                              Layout = new RawTimeStampLayout()

                                          });

                appender.AddParameter(new AdoNetAppenderParameter
                                          {
                                              ParameterName = "@Level",
                                              DbType = DbType.String,
                                              Layout = new Layout2RawLayoutAdapter(new PatternLayout("%level"))
                                          });

                appender.AddParameter(new AdoNetAppenderParameter
                                          {
                                              ParameterName = "@Logger",
                                              DbType = DbType.String,
                                              Layout = new Layout2RawLayoutAdapter(new PatternLayout("%logger"))
                                          });

                appender.AddParameter(new AdoNetAppenderParameter
                                          {
                                              ParameterName = "@Message",
                                              DbType = DbType.String,
                                              Layout = new RawPropertyLayout { Key = "RenderedMessage" }
                                          });

                appender.ActivateOptions();
                return appender;
            }

            public static void CreateLogDb(FileInfo file)
            {
                using (var conn = new SQLiteConnection())
                {
                    conn.ConnectionString = string.Format("Data Source={0};New=True;Compress=True;Synchronous=Off", file.FullName);
                    conn.Open();
                    var cmd = conn.CreateCommand();

                    cmd.CommandText =
                                     @"CREATE TABLE Log(
                            LogId     INTEGER PRIMARY KEY,
                            Date      DATETIME NOT NULL,
                            Level     VARCHAR(50) NOT NULL,
                            Logger    VARCHAR(255) NOT NULL,
                            Message   TEXT DEFAULT NULL
                        );";

                    cmd.ExecuteNonQuery();
                    cmd.Dispose();
                    conn.Close();
                }
            }
        }
    }
}

非常感谢。那个我要找很久才能找到。点赞并接受解决方案。 - Richard
@Richard,我花了比我想象中更长的时间才弄清楚。我一直在尝试通过调试log4net代码来让RawPropertyLayout起作用,但似乎它并不是为了获取某些属性而设计的。上面提到的方法是一个很好的解决办法。我们也使用SQLite,所以我们可能也会使用这个方法——这是我第一次使用带有ADO.NET的log4net。它非常棒。 - Samuel Neff

1

您尝试将缓冲区大小从100更改为1了吗?

appender.BufferSize = 100;

appender.BufferSize = 1;

目前您的文件需要等待100条消息才能输出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接