在ASP.NET Core中将EF Core的日志通过NLog输出到控制台
首先定义一个实现了ILogger接口的类EFLogger,主要目的是将EF Core生成的Log信息输出到NLog:
namespace AspNetCore8EFLogger.EF.Logger { public class EFLogger : ILogger { protected readonly ILogger<EFLogger> _logger; public string? CategoryName { get; set; } public EFLogger(ILogger<EFLogger> logger) { _logger = logger; } public IDisposable? BeginScope<TState>(TState state) where TState : notnull { return null; } public bool IsEnabled(LogLevel logLevel) { return true; } public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter) { //通过Log方法来将EF Core生成的Log信息输出到NLog中 _logger.Log(logLevel, 0, "=============================== EF Core log started ==============================="); _logger.Log(logLevel, 0, formatter(state, exception)); _logger.Log(logLevel, 0, "=============================== EF Core log finished ==============================="); } } }
然后定义一个实现了ILoggerFactory接口的类EFLoggerFactory,用于返回上面定义的EFLogger类的实例:
namespace AspNetCore8EFLogger.EF.Logger { public class EFLoggerFactory : ILoggerFactory { protected readonly EFLogger _logger; public EFLoggerFactory(EFLogger logger) { _logger = logger; } public void AddProvider(ILoggerProvider provider) { } public ILogger CreateLogger(string categoryName) { _logger.CategoryName = categoryName; return _logger;//返回EFLogger类的实例 } public void Dispose() { } } }
然后在DbContext的OnConfiguring方法中,调用optionsBuilder.UseLoggerFactory来将EFLoggerFactory类的实例注入给EF Core,这样所有DbContext的Log信息,都会由EFLogger类输出到NLog了。
using System; using System.Collections.Generic; using AspNetCore8EFLogger.EF.Logger; using Microsoft.EntityFrameworkCore; namespace AspNetCore8EFLogger.DB; public partial class MyDbContext : DbContext { protected readonly EFLoggerFactory _efLoggerFactory; public MyDbContext(EFLoggerFactory efLoggerFactory) { _efLoggerFactory = efLoggerFactory; } public virtual DbSet<Company> Companies { get; set; } public virtual DbSet<Department> Departments { get; set; } public virtual DbSet<NullTable> NullTables { get; set; } public virtual DbSet<Person> People { get; set; } public virtual DbSet<Staff> Staff { get; set; } public virtual DbSet<Student> Students { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { optionsBuilder.UseLoggerFactory(_efLoggerFactory);//将EFLoggerFactory类的实例注入给EF Core,这样所有DbContext的Log信息,都会由EFLogger类输出到NLog了 optionsBuilder.UseSqlServer("Server=localhost;User Id=Super;Password=Admin@123;Database=DemoDB;TrustServerCertificate=True"); } } protected override void OnModelCreating(ModelBuilder modelBuilder) { //省略代码... } partial void OnModelCreatingPartial(ModelBuilder modelBuilder); }
注意OnConfiguring这个方法是virtual的,所以我们也可以选择在DbContext的子类中来重写这个方法,在子类的OnConfiguring中注入EFLoggerFactory类的实例到DbContext。
然后我们给ASP.NET Core添加NuGet包:NLog.Web.AspNetCore
ASP.NET Core NLog官方文档链接:NLog.Web (ASP.NET & ASP.NET Core)
接着我们在ASP.NET Core的开始方法中,声明EFLogger、EFLoggerFactory、MyDbContext类的依赖注入关系,并且给ASP.NET Core添加NLog日志组件:
using AspNetCore8EFLogger.DB; using AspNetCore8EFLogger.EF.Logger; using NLog; using NLog.Extensions.Logging; using NLog.Web; namespace AspNetCore8EFLogger { public class Program { public static void Main(string[] args) { // Early init of NLog to allow startup and exception logging, before host is built var logger = NLog.LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger(); logger.Debug("init main"); try { var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); builder.Services.AddTransient<EFLogger>();//声明EFLogger类的依赖注入关系 builder.Services.AddTransient<EFLoggerFactory>();//声明EFLoggerFactory类的依赖注入关系 builder.Services.AddTransient<MyDbContext>();//声明MyDbContext类的依赖注入关系 builder.Logging.ClearProviders();//先清除ASP.NET Core的默认日志组件 builder.Logging.AddNLog();//然后给ASP.NET Core添加NLog日志组件 var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run(); logger.Debug("Application closing..."); } catch (Exception exception) { // NLog: catch setup errors logger.Error(exception, "Stopped program because of exception"); throw; } finally { // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) NLog.LogManager.Shutdown(); } } } }
然后我们在ASP.NET Core项目中创建一个NLog的配置文件nlog.config:
并在nlog.config文件中,将NLog配置为将日志输出到控制台:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" throwExceptions="false" > <targets> <!--添加一个新条目让日志输出到控制台中,并添加必要的输出布局(layout)--> <target name="console" xsi:type="Console" layout="${longdate}|${level}|${message}"/> <!--说明 xsi:type="Console"指定输出到控制台;layout指定输出文件内容的样式 ${longdate}是日期(具体到毫秒),${level}是日志的等级;${message}是具体要输出的内容。--> </targets> <rules> <!--添加必要的规则--> <logger name="*" writeTo="console"/> <!--我个人设置的规则是,将所有记录的信息输出至控制台--> </rules> </nlog>
注意nlog.config的文件属性如下:
最后我们在HomeController的构造方法中,依赖注入MyDbContext类的实例,并在Index这个Action方法中,做一个简单的EF Core查询:
using AspNetCore8EFLogger.DB; using Microsoft.AspNetCore.Mvc; namespace AspNetCore8EFLogger.Controllers { public class HomeController : Controller { private readonly ILogger<HomeController> _logger; private readonly MyDbContext _myDbContext; public HomeController(ILogger<HomeController> logger, MyDbContext myDbContext) { _logger = logger; _myDbContext = myDbContext; } public IActionResult Index() { List<Student> students; using (_myDbContext) { students = _myDbContext.Students.Where(s => s.Grade == "1").ToList(); } return View(); } } }
可以看到EF Core的日志,通过NLog输出到了控制台当中:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2020-01-16 await Task.Yield()和await Task.CompletedTask有什么不同
2019-01-16 .NET Core中向已存在文件的特定位置写入数据
2015-01-16 警惕ASP.NET MVC中的ValidateInputAttribute