在C#中实现数据库查询的日志记录,核心方式是通过拦截或捕获数据库操作过程中的SQL语句和执行时间。常用的技术和工具取决于你使用的数据访问方式,比如 Entity Framework、Dapper 或 ADO.NET。以下是几种常见实现方式和推荐工具。
1. Entity Framework 中的日志记录
如果你使用的是 Entity Framework(EF6 或 EF Core),它内置了日志支持。EF6:可以通过设置
DbContext.Database.Log属性来输出SQL日志。
示例:
context.Database.Log = message => System.Diagnostics.Debug.WriteLine(message);
也可以将日志写入文件或其他日志框架(如 NLog、Serilog)。
EF Core:使用
ILoggerFactory注册日志服务。
示例:
optionsBuilder.UseSqlServer(connectionString)
.LogTo(Console.WriteLine, LogLevel.Information);
还可以过滤只记录数据库命令:
.LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Command.Name }, LogLevel.Information)
2. 使用 Dapper 时的手动日志记录
Dapper 本身不提供自动日志功能,但你可以封装执行逻辑,在调用前后记录SQL和参数。建议做法:创建一个包装类,在执行 SQL 前后写日志。
示例:
public async Task<ienumerable>> QueryAsync<t>(string sql, object param = null)</t></ienumerable>
{_logger.LogInformation($"Executing SQL: {sql} with params: {param}");var result = await _connection.QueryAsync<t>(sql, param);</t>
_logger.LogInformation($"Query returned {result.Count()} results.");return result;
}
结合 Serilog 或 NLog 可以将日志结构化输出到文件、控制台或日志服务器。
3. 使用 ADO.NET 的拦截方案
对于原生 ADO.NET,需要手动在ExecuteNonQuery、
ExecuteReader等方法前后添加日志代码。
建议封装一个通用的数据库执行方法:
public async Task<t> ExecuteWithLoggingAsync<t>(string commandText, Func<sqlcommand task>> action)</sqlcommand></t></t>
{_logger.LogDebug($"SQL: {commandText}");var sw = Stopwatch.StartNew();
try
{var result = await action(cmd);
sw.Stop();
_logger.LogInformation($"SQL executed in {sw.ElapsedMilliseconds}ms");return result;
}
catch (Exception ex)
{_logger.LogError(ex, "SQL execution failed");
throw;
}
}
4. 推荐的日志工具
C# 生态中常用的日志库能很好地配合数据库日志记录: Serilog:支持结构化日志,可轻松输出到文件、Elasticsearch、Seq 等,适合生产环境。 NLog:配置灵活,性能好,支持多种目标(文件、数据库、网络等)。 Microsoft.Extensions.Logging:标准日志接口,可与上述实现集成,推荐用于 ASP.NET Core 项目。例如,使用 Serilog 记录EF Core日志:
.LogTo(Log.Logger.Information, LogLevel.Information)
基本上就这些。根据你的数据访问技术选择合适的方式,关键是把SQL、参数、执行时间和异常统一记录下来,便于排查问题和性能分析。
