ABP记录EF生成的数据库日志

1.首先我们建两个类来记录EFCore产生的脚本日志

using Microsoft.Extensions.Logging;
using System;

namespace STK.backendCode.EntityFrameworkCore.Logger
{
    public class EFLogger : ILogger
    {
        public Castle.Core.Logging.ILogger Logger { get; set; }

        private readonly string _categoryName;

        public EFLogger(string categoryName, Castle.Core.Logging.ILogger logger)
        {
            this._categoryName = categoryName;
            this.Logger = logger;
        }

        public bool IsEnabled(LogLevel logLevel) => true;

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
            Func<TState, Exception, string> formatter)
        {
            //ef core执行数据库查询时的categoryName为Microsoft.EntityFrameworkCore.Database.Command,日志级别为Information
            var logContent2 = formatter(state, exception);
            if (_categoryName == "Microsoft.EntityFrameworkCore.Database.Command"
                && logLevel == LogLevel.Information)
            {
                var logContent = formatter(state, exception);
                Logger.Warn(logContent);
            }
        }

        public IDisposable BeginScope<TState>(TState state) => null;
    }
}
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;

namespace STK.backendCode.EntityFrameworkCore.Logger
{
    public class EfLoggerProvider : ILoggerProvider
    {
        public Castle.Core.Logging.ILogger Logger;

        public EfLoggerProvider(Castle.Core.Logging.ILogger logger)
        {
            Logger = logger;
        }

        public ILogger CreateLogger(string categoryName)
        {
            return new EFLogger(categoryName, Logger);
        }

        public void Dispose()
        {
        }
    }
}

 

2.修改AbpDemoDbContextConfigurer.cs

using System.Data.Common;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace STK.backendCode.EntityFrameworkCore
{
    public static class backendCodeDbContextConfigurer
    {
        public static void Configure(DbContextOptionsBuilder<backendCodeDbContext> builder, string connectionString, LoggerFactory loggerFactory)
        {
            //builder.UseSqlServer(connectionString);
            builder.UseLoggerFactory(loggerFactory).UseMySql(connectionString);
            builder.EnableSensitiveDataLogging(); //日志显示脚本参数
        }

        public static void Configure(DbContextOptionsBuilder<backendCodeDbContext> builder, DbConnection connection, LoggerFactory loggerFactory)
        {
            //builder.UseSqlServer(connection);
            builder.UseLoggerFactory(loggerFactory).UseMySql(connection);
            builder.EnableSensitiveDataLogging(); //日志显示脚本参数
        }
    }
}

 

3, 修改AbpDemoEntityFrameworkModule.cs   构建EfLoggerProvider类并提供给配置类使用

using Abp.EntityFrameworkCore.Configuration;
using Abp.Modules;
using Abp.Reflection.Extensions;
using Abp.Zero.EntityFrameworkCore;
using STK.backendCode.EntityFrameworkCore.Logger;
using STK.backendCode.EntityFrameworkCore.Seed;

namespace STK.backendCode.EntityFrameworkCore
{
    [DependsOn(
        typeof(backendCodeCoreModule), 
        typeof(AbpZeroCoreEntityFrameworkCoreModule))]
    public class backendCodeEntityFrameworkModule : AbpModule
    {
        /* Used it tests to skip dbcontext registration, in order to use in-memory database of EF Core */
        public bool SkipDbContextRegistration { get; set; }

        public bool SkipDbSeed { get; set; }

        public override void PreInitialize()
        {
            if (!SkipDbContextRegistration)
            {
                Configuration.Modules.AbpEfCore().AddDbContext<backendCodeDbContext>(options =>
                {
                    if (options.ExistingConnection != null)
                    {
                        backendCodeDbContextConfigurer.Configure(options.DbContextOptions, options.ExistingConnection, DbLoggerFactory);
                    }
                    else
                    {
                        backendCodeDbContextConfigurer.Configure(options.DbContextOptions, options.ConnectionString, DbLoggerFactory);
                    }
                });
            }
        }

        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(typeof(backendCodeEntityFrameworkModule).GetAssembly());
        }

        public override void PostInitialize()
        {
            if (!SkipDbSeed)
            {
                SeedHelper.SeedHostDb(IocManager);
            }
        }

        private static Microsoft.Extensions.Logging.LoggerFactory _loggerFactory;

        private Microsoft.Extensions.Logging.LoggerFactory DbLoggerFactory
        {
            get
            {
                if (null == _loggerFactory)
                {
                    _loggerFactory = new Microsoft.Extensions.Logging.LoggerFactory();
                    //_loggerFactory.AddProvider(new EfLoggerProvider(IocManager.Resolve<Castle.Core.Logging.ILogger>()));
                    _loggerFactory.AddProvider(new EfLoggerProvider(Logger));
                }

                return _loggerFactory;
            }
        }
    }
}

 

4, 修复AbpDemoDbContextFactory.cs 的报错,传入空日志类就可以了

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using STK.backendCode.Configuration;
using STK.backendCode.Web;

namespace STK.backendCode.EntityFrameworkCore
{
    /* This class is needed to run "dotnet ef ..." commands from command line on development. Not used anywhere else */
    public class backendCodeDbContextFactory : IDesignTimeDbContextFactory<backendCodeDbContext>
    {
        public backendCodeDbContext CreateDbContext(string[] args)
        {
            var builder = new DbContextOptionsBuilder<backendCodeDbContext>();
            var configuration = AppConfigurations.Get(WebContentDirectoryFinder.CalculateContentRootFolder());

            backendCodeDbContextConfigurer.Configure(builder, configuration.GetConnectionString(backendCodeConsts.ConnectionStringName), null);

            return new backendCodeDbContext(builder.Options);
        }
    }
}

这样运行项目, 在Logs.txt中就会显示所有的数据库脚本了

 

我对日志进行了分类存放, 下面是参考的 log4net.config

<?xml version="1.0" encoding="utf-8" ?>
<log4net>

  <!-- 全部的日志 DEBUG < INFO < WARN < ERROR < FATAL -->
  <appender name="Info" type="log4net.Appender.RollingFileAppender" >
    <file value="App_Data/Logs/Info" />
    <appendToFile value="true" />
    <rollingStyle value="Date" />
    <datePattern value="yyyyMM\\'Info'yyyyMMdd'.txt'"/>
    <maxSizeRollBackups value="100" />
    <maximumFileSize value="10000KB" />
    <staticLogFileName value="false" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%newline%date [%thread] [%-5level] %logger %newline%message%newline"/>
    </layout>
  </appender>

  <!-- SQL -->
  <appender name="Warn" type="log4net.Appender.RollingFileAppender" >
    <file value="App_Data/Logs/Warn" />
    <appendToFile value="true" />
    <rollingStyle value="Date" />
    <datePattern value="yyyyMM\\'Warn'yyyyMMdd'.txt'"/>
    <maxSizeRollBackups value="100" />
    <maximumFileSize value="10000KB" />
    <staticLogFileName value="false" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%newline%date [%thread] [%-5level] %logger %newline%message%newline"/>
    </layout>
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="Warn" />
      <levelMax value="Warn" />
    </filter>
  </appender>

  <!-- Error -->
  <appender name="Error" type="log4net.Appender.RollingFileAppender" >
    <file value="App_Data/Logs/Error" />
    <appendToFile value="true" />
    <rollingStyle value="Date" />
    <datePattern value="yyyyMM/'Error'yyyyMMdd'.txt'"/>
    <maxSizeRollBackups value="100" />
    <maximumFileSize value="10000KB" />
    <staticLogFileName value="false" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%newline%date [%thread] [%-5level] %logger property: [%property{NDC}] %newline%message%newline"/>
    </layout>
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="Error" />
    </filter>
  </appender>

  <!-- 只有Debug -->
  <appender name="Debug" type="log4net.Appender.RollingFileAppender" >
    <file value="App_Data/Logs/Debug.txt" />
    <appendToFile value="true" />
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="10" />
    <maximumFileSize value="10000KB" />
    <staticLogFileName value="true" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%newline%date [%thread] [%-5level] %logger %newline%message%newline"/>
    </layout>
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="Debug" />
      <levelMax value="Debug" />
    </filter>
  </appender>

  <!--输出到控制台-->
  <appender name="Console" type="log4net.Appender.ManagedColoredConsoleAppender">
    <mapping>
      <level value="ERROR">
        <foreColor value="Yellow,HighIntensity" />
      </level>
    </mapping>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%newline%date [%thread] [%-5level] %-40.40logger %newline%message%newline" />
    </layout>
    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="Error" />
    </filter>
  </appender>

  <root>
    <appender-ref ref="Warn" />
    <appender-ref ref="Info" />
    <appender-ref ref="Error" />
    <appender-ref ref="Debug" />
    <appender-ref ref="Console" />
    <level value="DEBUG" />
  </root>

  <logger name="NHibernate">
    <level value="WARN" />
  </logger>
</log4net>

 

posted @ 2022-03-17 15:08  殇琉璃  阅读(384)  评论(0编辑  收藏  举报