• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
PowerCoder
博客园    首页    新随笔    联系   管理    订阅  订阅

在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输出到了控制台当中:

 

posted @ 2025-01-16 21:37  PowerCoder  阅读(201)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3