在 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 应用程序
ASP.NET Core 应用程序中默认使用 Microsoft.Extensions.Logging
。 调用 AddDbContext 或 AddDbContextPool 可使 EF Core 自动使用通过常规 ASP.NET 机制配置的日志记录设置。
其他应用程序类型
其他应用程序类型可使用 GenericHost 获取与 ASP.NET Core 中使用的相同的依赖项注入模式。 然后,可像在 ASP.NET Core 应用程序中一样使用 AddDbContext 或 AddDbContextPool。
Microsoft.Extensions.Logging
也可用于不使用依赖项注入的应用程序,尽管设置简单的日志记录更容易。
Microsoft.Extensions.Logging
需要创建 LoggerFactory。 此工厂应存储为静态/全局实例,并在每次创建 DbContext 时使用。 例如,通常将记录器工厂存储为 DbContext 上的静态属性。
public static readonly ILoggerFactory MyLoggerFactory
= LoggerFactory.Create(builder => { builder.AddConsole(); });
然后应在 DbContextOptionsBuilder 上向 EF Core 注册此单一实例/全局实例。 例如:
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.Debug
提升到 LogLevel.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。
这些定义包含 Microsoft.Extensions.Logging
使用的每个事件的事件 ID、日志级别和类别。