要切换EF核心SQL日志(log)记录,可以在appsettings.json中使用以下命令:

"Logging": {
  "LogLevel": {
    //...
    "Microsoft.EntityFrameworkCore.Database.Command": "Information" //or "Warning"
  }
}

在开发过程中,EF Core默认在"信息"级别记录查询;因此可以使用"警告"使其静音.

But that applies to both reads and writes.当我遇到EF问题时,几乎总是与写入有关-所以我启用了日志(log)记录,并获得了大量的读取日志(log),这使得调试变得困难.

是否可以分别切换读取和写入的日志(log)记录?

推荐答案

是否可以分别切换读取和写入的日志(log)记录?

Use this in only Development Environment

我会这样做:

使用DbCommandInterceptor类拦截执行的SQL语句. 因此,首先我创建一个继承DbCommandInterceptor的类QueryCommandInterceptor :

public class QueryCommandInterceptor : DbCommandInterceptor
{
 private readonly ILogger<QueryCommandInterceptor> _logger;

 public QueryCommandInterceptor(ILogger<QueryCommandInterceptor> logger)
 {
     _logger = logger;
 }
}

添加该方法以判断该命令是否为写操作,即DELETEUPDATEINSERT,如果是,还记录该命令:

private void LogCommand(DbCommand command)
{
    if (command.CommandText.Contains("INSERT") ||
           command.CommandText.Contains("UPDATE") ||
           command.CommandText.Contains("DELETE"))
    {
        _logger.LogInformation($"Executing SQL command: {command.CommandText}");
    }
}

DbCommandInterceptor中的最后QueryCommandInterceptor个重写方法:

using Microsoft.EntityFrameworkCore.Diagnostics;
using System.Data.Common;

namespace StackOverflow
{
    public class QueryCommandInterceptor : DbCommandInterceptor
    {
        private readonly ILogger<QueryCommandInterceptor> _logger;

        public QueryCommandInterceptor(ILogger<QueryCommandInterceptor> logger)
        {
            _logger = logger;
        }
        public override InterceptionResult<int> NonQueryExecuting(
           DbCommand command,
           CommandEventData eventData,
           InterceptionResult<int> result)
        {
            LogCommand(command);
            return result;
        }

        public override ValueTask<InterceptionResult<int>> NonQueryExecutingAsync(
            DbCommand command,
            CommandEventData eventData,
            InterceptionResult<int> result,
            CancellationToken cancellationToken = default)
        {
            LogCommand(command);
            return new ValueTask<InterceptionResult<int>>(result);
        }

        public override InterceptionResult<DbDataReader> ReaderExecuting(
            DbCommand command,
            CommandEventData eventData,
            InterceptionResult<DbDataReader> result)
        {
            LogCommand(command);
            return result;
        }

        public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(
            DbCommand command,
            CommandEventData eventData,
            InterceptionResult<DbDataReader> result,
            CancellationToken cancellationToken = default)
        {
            LogCommand(command);
            return new ValueTask<InterceptionResult<DbDataReader>>(result);
        }

        public override InterceptionResult<object> ScalarExecuting(
           DbCommand command,
           CommandEventData eventData,
           InterceptionResult<object> result)
        {
            LogCommand(command);
            return result;
        }

        public override ValueTask<InterceptionResult<object>> ScalarExecutingAsync(
            DbCommand command,
            CommandEventData eventData,
            InterceptionResult<object> result,
            CancellationToken cancellationToken = default)
        {
            LogCommand(command);
            return new ValueTask<InterceptionResult<object>>(result);
        }
        private void LogCommand(DbCommand command)
        {
            if (command.CommandText.Contains("INSERT") ||
                   command.CommandText.Contains("UPDATE") ||
                   command.CommandText.Contains("DELETE"))
            {
                _logger.LogInformation($"Executing SQL command: {command.CommandText}");
            }
        }
       
    }
}

最后,在我的Program.cs中连接我的记录器,也添加了新的拦截器:

builder.Logging.ClearProviders();
var logger = LoggerFactory.Create(builder =>
{
    builder.AddConsole();
}).CreateLogger<QueryCommandInterceptor>();

builder.Services.AddDbContext<StackContext>(options => 
{
    options.UseSqlServer(connectionString);
    options.AddInterceptors(new QueryCommandInterceptor(logger)); 
}
);

Csharp相关问答推荐

如何打印已添加到List的Linq值,而不是C#中的:System.Collections.Generic.List ' 1[System.Int32]?

Blazor-从数据库内部服务器提取错误

如何使用C#Interop EXCEL创建度量衡

有没有办法使.NET 6应用程序在特定的.NET 6运行时版本上运行

如何在不考虑年份的情况下判断日期时间是否在某个日期范围内?

注册所有IMediatR类

如何使用C#中的主构造函数功能使用多个构造函数?

从.Net 6 DLL注册和检索COM对象(Typelib导出:类型库未注册.(异常来自HRESULT:0x80131165))

单元测试:模拟返回空

在C#中,将两个哈希集连接在一起的时间复杂度是多少?

C#Null判断处理失败

是否有必要在ASP.NET Core中注册可传递依赖项?

在集成测试中可以在模拟InMemory数据库中设定数据种子

是否可以从IQueryable T中获取一个IdentyEntry T>

如何正确处置所有动态控件?

ASP.NET MVC数据批注验证组复选框

RCL在毛伊岛应用程序和Blazor服务器应用程序.Net 8.0中使用页面

NETSDK1201:对于面向.NET 8.0和更高版本的项目,默认情况下,指定RUNTIME标识符将不再生成自包含的应用程序

身份验证中间件如何处理多个方案

.NET6最小API:操作.MapGet之后的响应