我正在尝试基于 log4net 库实现数据库记录器。我需要将我的日志写入 MySql 数据库。当我将一些硬编码值记录到我的日志表中时,一切都很好。当我尝试将至少一个参数传递给我的查询时,log4net 开始抱怨“准备期间未找到参数'@message'”。我发现了一个丑陋的解决方法,我实现了自己的 AdoNetAppender,并在其中将我的值传递给查询。但正如我所说,这是肮脏且不安全的解决方案。我想避免这种情况。我花了一整天的时间,我没有更多的想法如何以干净的方式解决它。
我的项目设置如下:Net Core 3.1、log4Net 2.0.12。
你知道为什么它不起作用吗?
先感谢您!
在我的代码下面:
namespace Application.Logging.Implementation
{
public class DatabaseLogger : LoggerBase, Interfaces.ILogger
{
private static readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public void LogDebug(string message, params object[] parameters)
{
_logger.Debug(buildLogMessage(message, parameters));
}
public void LogError(string message, params object[] parameters)
{
_logger.ErrorFormat(buildLogMessage(message, parameters));
}
public void LogInfo(string message, params object[] parameters)
{
_logger.InfoFormat(buildLogMessage(message, parameters));
}
protected override void configure()
{
AdoNetAppender dbAppender = new AdoNetAppender();
dbAppender.BufferSize = 1;
dbAppender.ConnectionString = "Server=<server_ip>;Database=<db_name>;Uid=<user_name>;Pwd=<password>;";
dbAppender.ConnectionType = "MySql.Data.MySqlClient.MySqlConnection, MySql.Data";
dbAppender.CommandType = System.Data.CommandType.Text;
dbAppender.CommandText = "INSERT INTO LOG (LOG_DATE, LOG_LEVEL, LOG_MESSAGE) VALUES (Now(), 'DEBUG', @message)";
dbAppender.ErrorHandler = new CustomErrorHandler();
var dbParam = new AdoNetAppenderParameter
{
ParameterName = "@message",
DbType = System.Data.DbType.String,
Layout = (IRawLayout)new RawLayoutConverter().ConvertFrom(new PatternLayout('%message'))
};
dbAppender.AddParameter(dbParam);
dbAppender.ActivateOptions();
Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
hierarchy.Root.AddAppender(dbAppender);
hierarchy.Root.Level = Level.All;
hierarchy.Configured = true;
log4net.Config.BasicConfigurator.Configure(hierarchy);
}
}
}
解决方法:我使用了一些预定义的字符串,而不是查询中的@message 参数,并将其替换为自己的 AdoNetAppenderParameter。我意识到它不能像这样工作......
namespace Application.Logging.Implementation
{
public class MessageAdoNetAppenderParameter : AdoNetAppenderParameter
{
public UserAdoNetAppenderParameter()
{
}
public override void Prepare(IDbCommand command)
{
}
public override void FormatValue(IDbCommand command, LoggingEvent loggingEvent)
{
var data = loggingEvent.RenderedMessage;
command.CommandText = command.CommandText.Replace("'<message>'", $"'{data}'");
}
}
}