如何在EF Core自定义内部服务中使用内置日志器?
解决EF Core自定义类型映射源的日志输出问题
问题根源
你手动从IServiceProvider获取IDiagnosticsLogger的方式无法关联到OnConfiguring中配置的LoggerFactory,因为EF Core的服务初始化顺序导致此时诊断日志器尚未绑定正确的日志提供者。正确的做法是通过构造函数直接注入EF框架管理的诊断日志器。
解决方案
1. 修正自定义类型映射源的构造函数
直接注入IDiagnosticsLogger<T>(使用EF的日志分类,比如DbLoggerCategory.Infrastructure),而非手动从服务容器获取。这样日志器会自动关联你配置的Debug和Console提供者,输出格式与EF原生日志一致。
public class CustomSqlServerTypeMappingSource : SqlServerTypeMappingSource { private readonly IDiagnosticsLogger<DbLoggerCategory.Infrastructure> _diagnosticsLogger; // 注入基类依赖 + EF诊断日志器 public CustomSqlServerTypeMappingSource( TypeMappingSourceDependencies dependencies, RelationalTypeMappingSourceDependencies relationalDependencies, IDiagnosticsLogger<DbLoggerCategory.Infrastructure> diagnosticsLogger) : base(dependencies, relationalDependencies) { _diagnosticsLogger = diagnosticsLogger; // 输出初始化日志,格式与EF原生一致 _diagnosticsLogger.Logger.LogInformation( new EventId(10404, "CustomTypeMappingSourceInitialized"), "已创建自定义SqlServer类型映射源"); } // 示例:自定义类型映射逻辑 + 日志输出 protected override RelationalTypeMapping FindMapping(in RelationalTypeMappingInfo mappingInfo) { _diagnosticsLogger.Logger.LogDebug( new EventId(10405, "CustomTypeMappingLookup"), "正在查找类型映射:{MappingInfo}", mappingInfo); // 你的自定义映射逻辑 var mapping = base.FindMapping(mappingInfo); if (mapping == null) { _diagnosticsLogger.Logger.LogWarning( new EventId(10406, "CustomTypeMappingNotFound"), "未找到类型映射:{MappingInfo}", mappingInfo); } return mapping; } }
2. 确认DbContext配置顺序(可选)
确保UseLoggerFactory在服务替换前配置(EF Core配置顺序不强制,但提前配置日志能确保所有服务都使用同一日志提供者):
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); // 先配置日志工厂 ILoggerFactory loggerFactory = LoggerFactory.Create(logging => logging.AddDebug() .AddConsole() .SetMinimumLevel(LogLevel.Trace)); optionsBuilder.UseLoggerFactory(loggerFactory); // 替换类型映射源服务 optionsBuilder.ReplaceService<IRelationalTypeMappingSource, CustomSqlServerTypeMappingSource>(); optionsBuilder.EnableSensitiveDataLogging(); optionsBuilder.UseSqlServer("Server=..."); }
输出效果
运行后会输出与EF原生日志格式完全一致的内容:
info: Microsoft.EntityFrameworkCore.Infrastructure[10404] 已创建自定义SqlServer类型映射源 dbug: Microsoft.EntityFrameworkCore.Infrastructure[10405] 正在查找类型映射:Microsoft.EntityFrameworkCore.Storage.RelationalTypeMappingInfo
内容的提问来源于stack exchange,提问作者Jossean Yamil
相关产品推荐
相关产品推荐

