在 EF Core 中使用 Microsoft.Extensions.Logging

Microsoft.Extensions.Logging 是一种可扩展的日志记录机制,其中包含许多常见日志记录系统的插件提供程序。 Microsoft提供的插件(例如 Microsoft.Extensions.Logging.Console)和第三方插件(例如 Serilog.Extensions.Logging)都可用作 NuGet 包。

Entity Framework Core(EF Core)与Microsoft.Extensions.Logging完全集成。 但是,请考虑使用 简单日志记录 来记录更简单的方法,尤其是对于不使用依赖项注入的应用程序。

ASP.NET Core 应用程序

Microsoft.Extensions.Logging 在 ASP.NET Core 应用程序中默认使用。 调用 AddDbContextAddDbContextPool 使 EF Core 自动使用通过常规 ASP.NET 机制配置的日志记录设置。

其他应用程序类型

其他应用程序类型可以使用 GenericHost 获取与 ASP.NET Core 中使用的相同依赖项注入模式。 AddDbContextAddDbContextPool 随后可以像在 ASP.NET Core 应用程序中一样使用。

Microsoft.Extensions.Logging 也可用于不使用依赖项注入的应用程序,尽管 简单的日志记录 更易于设置。

Microsoft.Extensions.Logging 需要创建一个 LoggerFactory。 此工厂应存储为静态/全局实例,并在每次创建 DbContext 时使用。 例如,通常将记录器工厂存储为 DbContext 上的静态属性。

public static readonly ILoggerFactory MyLoggerFactory
    = LoggerFactory.Create(builder => { builder.AddConsole(); });

然后,应在 EF Core 中注册此单例或全局实例DbContextOptionsBuilder。 例如:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseLoggerFactory(MyLoggerFactory)
        .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFLogging;Trusted_Connection=True;ConnectRetryCount=0");

获取详细消息

小窍门

在使用 AddDbContext 或将 DbContextOptions 实例传递给 DbContext 构造函数时,仍会调用 OnConfiguring。 这样,无论如何构造 DbContext,它都是应用上下文配置的理想位置。

敏感数据

默认情况下,EF Core 不会在异常消息中包含任何数据的值。 这是因为此类数据可能是机密的,在未处理异常的情况下,这些数据可能会在生产使用中被泄露。

但是,了解数据值(尤其是键)在调试时非常有用。 这可以通过调用 EnableSensitiveDataLogging()在 EF Core 中启用。 例如:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.EnableSensitiveDataLogging();

详细的查询异常

出于性能原因,EF Core 不会在 try-catch 块中对每次从数据库提供程序读取值的调用进行包装。 但是,这有时会导致难以诊断的异常,尤其是在模型不允许时数据库返回 NULL 时。

启用EnableDetailedErrors将导致 EF 引入这些 try-catch 块,从而提供更详细的错误信息。 例如:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.EnableDetailedErrors();

特定消息的配置

EF Core ConfigureWarnings API 允许应用程序更改遇到特定事件时发生的情况。 这可用于:

  • 更改记录事件的日志级别
  • 完全不记录事件
  • 事件发生时引发异常

更改事件的日志级别

有时,更改事件的预定义日志级别可能很有用。 例如,这可用于在 LogLevel.DebugLogLevel.Information 之间推广另外两个事件:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(
            b => b.Log(
                (RelationalEventId.ConnectionOpened, LogLevel.Information),
                (RelationalEventId.ConnectionClosed, LogLevel.Information)));

禁止记录事件

类似地,可以从日志记录中禁止单个事件。 这对于忽略已审阅和理解的警告特别有用。 例如:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(b => b.Ignore(CoreEventId.DetachedLazyLoadingWarning));

触发事件

最后,可以将 EF Core 配置为为给定事件引发。 这对于将警告更改为错误特别有用。 事实上,这正是ConfigureWarnings方法的初衷,因此得名。例如:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(b => b.Throw(RelationalEventId.QueryPossibleUnintendedUseOfEqualsWarning));

筛选和其他配置

有关日志筛选和其他配置的指导,请参阅 .NET 中的日志记录

EF Core 日志记录事件被定义为以下之一:

  • CoreEventId 用于适用于所有 EF Core 数据库提供者的通用事件
  • RelationalEventId 用于所有关系数据库提供程序中常见事件
  • 特定于当前数据库提供程序的事件的类似类。 例如,对于 SQL Server 提供者,SqlServerEventId

这些定义包含每个事件的事件 ID、日志级别和类别,供Microsoft.Extensions.Logging使用。