C# Log4Net实现日志文件 保存数据库
一、创建一个WinForm的项目,并通过NuGet安装log4net。
二、创建LogHelper类以及log4net.config配置文件。
三、编写相关代码。
1、log4net.config类
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<root>
</root>
<appender name="InfoAppender" type="log4net.Appender.RollingFileAppender,log4net" >
<param name="File" type="" value="Log/Error/" />
<param name="AppendToFile" value="true" />
<param name="RollingStyle" value="Date" />
<param name="DatePattern" value="yyyyMMdd".ini"" />
<param name="StaticLogFileName" value="false" />
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="[%d]%n%m%n" />
</layout>
</appender>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="0" />
<connectionType value="System.Data.SQLite.SQLiteConnection,System.Data.SQLite" />
<connectionString value="Data Source=DataBase\\Log4NetSQLite.db;Version=3;" />
<commandText value="INSERT INTO Log (Date, Level, Logger, Message) VALUES (@Date, @Level, @Logger, @Message)" />
<parameter>
<parameterName value="@Date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@Level" />
<dbType value="String" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@Logger" />
<dbType value="String" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@Message" />
<dbType value="String" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
</appender>
<logger name="Error">
<level value="ERROR" />
<appender-ref ref="InfoAppender" />
</logger>
<logger name="Info">
<level value="INFO" />
<appender-ref ref="AdoNetAppender" />
</logger>
</log4net>
</configuration>
其中,较为重要的是日志信息的格式,对应上面文件中的ConversionPattern,值为"[%d]%n%m%n%n",每个占位符有对应的含义,如下所示:
字符格式说明:%m(message)
输出的日志消息
%n(newline) //换行
%d(datetime) //输出当前语句运行的时刻
%r(runtime) //输出程序执行到当前消耗的毫秒数
%t(threadid) //当前语句所在的线程ID
%p(priority) //日志的当前日志级别
%c(class) //当前日志对象的名称
%L //输出语句所在的行号
%F //输出语句所在的文件名
%-10 //最小长度为10,不够空格填充
2.LogHelper类
public class LogHelper
{
/// <summary>
/// 普通日志
/// </summary>
/// <param name="message">日志内容</param>
public static void Info(string message)
{
ILog log = LogManager.GetLogger("Info");
if (log.IsInfoEnabled)
{
log.Info(message);
}
}
/// <summary>
/// 错误日志带异常
/// </summary>
/// <param name="message">错误日志</param>
public static void Error(string message, Exception ex)
{
ILog log = LogManager.GetLogger("Error");
if (log.IsErrorEnabled)
{
log.Error(message, ex);
}
}
/// <summary>
/// 错误日志不带异常
/// </summary>
/// <param name="message">错误日志</param>
public static void Error(string message)
{
ILog log = LogManager.GetLogger("Error");
if (log.IsErrorEnabled)
{
log.Error(message);
}
}
}
3、将log4net.config设为始终复制。
四、在AssemblyInfo.cs添加以下代码
[assembly: AssemblyTitle("Log4NetSQLiteFuniyi")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Log4NetSQLiteFuniyi")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", ConfigFileExtension = "config", Watch = true)]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("4fea8622-fd5b-4aca-a2dd-96f2c5c74e4c")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
五、添加 System.Data.SQLite
六、添加测试代码并运行
public partial class FrmMain : Form { public FrmMain() { InitializeComponent(); } private void btn_ini_Click(object sender, EventArgs e) { this.lab_ini.Text = ""; //不带异常 LogHelper.Error(this.txt_ini.Text.Trim()); //带异常 LogHelper.Error(this.txt_ini.Text.Trim(), new Exception("这是一条异常错误信息")); this.lab_ini.Text = "写入完成"; } private void btn_SQLite_Click(object sender, EventArgs e) { this.lab_sql.Text = ""; //日志信息写入数据库 LogHelper.Info(this.txt_SQLite.Text.Trim()); LogHelper.Info(new Exception("这是一条异常错误信息").ToString()); this.lab_sql.Text = "写入完成"; }
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决