ef core 6+ 推荐用 logto(console.writeline, new[] { dbloggercategory.database.command.name }) 一行启用sql日志,需指定类别避免被过滤;默认不展开参数值以保障安全,生产环境禁用敏感数据日志。

EF Core 6+ 怎么开启 SQL 日志输出
默认情况下 EF Core 不打印任何 SQL,必须显式配置日志提供者。最直接有效的方式是配置 Microsoft.EntityFrameworkCore.Database.Command 类别为 Debug 或 Information 级别——不是靠改 DbContext.OnConfiguring 里随便加个 LogTo 就完事,得确保日志框架能真正捕获到。
- 在
Program.cs中用ConfigureLogging添加ConsoleLoggerProvider,并设置最低级别为Debug - 或者更推荐:直接在
DbContext.OnConfiguring里调用options.LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Command.Name }),这样不依赖外部日志系统,开箱即用 - 注意:EF Core 5 及以前用的是
options.UseLoggerFactory(...),6+ 已弃用,混用会导致日志静默丢失
为什么 LogTo 看不到参数值(只显示 @p0、@p1)
LogTo 默认只输出带参数占位符的 SQL 模板,不展开实际参数值。这不是 bug,是设计使然——避免敏感数据意外泄露。真要看到完整语句(含参数代入),得自己拼接或换方式。
- 手动拼接:监听
DiagnosticSource的Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting事件,在事件中读取command.Parameters并替换@p0等占位符(注意类型转换,比如DateTime要加单引号,null要转成NULL) - 更省事:用第三方包
Z.EntityFramework.Extensions或EFCore.BulkExtensions提供的 SQL 日志钩子,它们内置了参数展开逻辑 - 警告:生产环境禁用参数展开,尤其涉及密码、手机号等字段时,
LogTo的默认行为反而是安全底线
如何拦截并修改 EF Core 发出的 SQL(比如加 schema 前缀或审计字段)
EF Core 不允许直接篡改最终执行的 SQL 字符串,但可以通过 IRelationalCommandBuilderFactory 替换底层命令构建器,或更常用的是用 IDbCommandInterceptor 在命令执行前介入。
- 实现
IDbCommandInterceptor,重写CommandExecuting方法,在里面读取command.CommandText并做字符串替换(例如把FROM Users改成FROM dbo.Users) - 注册拦截器时必须用
services.AddEntityFrameworkSqlServer().AddInterceptors(...),不能只调AddSingleton,否则 EF Core 不会识别 - 注意:拦截器对
FromSqlRaw和迁移命令也生效,加逻辑前先用command.CommandText.StartsWith("SELECT")过滤,避免误改
在非控制台项目(如 ASP.NET Core Web API)里看不到 SQL 日志怎么办
不是代码没生效,而是日志被 ASP.NET Core 默认的日志过滤规则吞掉了。Web 项目默认把 Microsoft.EntityFrameworkCore 相关日志设为 Warning 级别以上,Information 级别的 SQL 日志直接被丢弃。
- 检查
appsettings.Development.json,确保有:"Logging": { "LogLevel": { "Default": "Information", "Microsoft.EntityFrameworkCore.Database.Command": "Information" } } - 如果用
LogTo,确认它没被后续的ConfigureLogging调用覆盖——后者会清空之前所有提供者 - IIS Express 下有时控制台被隐藏,建议改用
Debug.WriteLine或写入文件,验证是否真没输出
UseLoggerFactory 彻底失效这点,很多人查半天文档才发现是版本断层问题。











