1. 程式人生 > >ABP.Net Core使用教程(三)記錄數據庫腳本日誌

ABP.Net Core使用教程(三)記錄數據庫腳本日誌

med else hibernate actor otn bubuko 行數 creat %d

可以跟蹤數據庫腳本能很好的幫助我們理解ABP , SQL Server Profiler當然是很好的工具 , 好像MySQL沒有這麽方便的工具

這裏我們討論用日誌記錄的方法

1, 首先我們建兩個類來記錄EFCore產生的腳本日誌

技術分享圖片

EFLogger.cs

技術分享圖片
using Microsoft.Extensions.Logging;
using System;

namespace AbpDemo.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; } }
View Code

EfLoggerProvider.cs

技術分享圖片
using Microsoft.Extensions.Logging;

namespace AbpDemo.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()
        {
        }
    }
}
View Code

2, 修改AbpDemoDbContextConfigurer.cs

技術分享圖片
using System.Data.Common;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace AbpDemo.EntityFrameworkCore
{
    public static class AbpDemoDbContextConfigurer
    {
        public static void Configure(DbContextOptionsBuilder<AbpDemoDbContext> builder, string connectionString,
            LoggerFactory loggerFactory)
        {
            builder.UseLoggerFactory(loggerFactory).UseSqlServer(connectionString);
            builder.EnableSensitiveDataLogging(); //日誌顯示腳本參數
        }

        public static void Configure(DbContextOptionsBuilder<AbpDemoDbContext> builder, DbConnection connection,
            LoggerFactory loggerFactory)
        {
            builder.UseLoggerFactory(loggerFactory).UseSqlServer(connection);
            builder.EnableSensitiveDataLogging(); //日誌顯示腳本參數
        }
    }
}
View Code

3, 修改AbpDemoEntityFrameworkModule.cs 構建EfLoggerProvider類並提供給配置類使用

技術分享圖片
using Abp.EntityFrameworkCore.Configuration;
using Abp.Modules;
using Abp.Reflection.Extensions;
using Abp.Zero.EntityFrameworkCore;
using AbpDemo.EntityFrameworkCore.Logger;
using AbpDemo.EntityFrameworkCore.Seed;

namespace AbpDemo.EntityFrameworkCore
{
    [DependsOn(
        typeof(AbpDemoCoreModule),
        typeof(AbpZeroCoreEntityFrameworkCoreModule))]
    public class AbpDemoEntityFrameworkModule : 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<AbpDemoDbContext>(options =>
                {
                    if (options.ExistingConnection != null)
                    {
                        AbpDemoDbContextConfigurer.Configure(options.DbContextOptions, options.ExistingConnection,
                            DbLoggerFactory);
                    }
                    else
                    {
                        AbpDemoDbContextConfigurer.Configure(options.DbContextOptions, options.ConnectionString,
                            DbLoggerFactory);
                    }
                });
            }
        }

        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(typeof(AbpDemoEntityFrameworkModule).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;
            }
        }
    }
}
View Code

4, 修復AbpDemoDbContextFactory.cs 的報錯,傳入空日誌類就可以了

技術分享圖片
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using AbpDemo.Configuration;
using AbpDemo.Web;

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

            AbpDemoDbContextConfigurer.Configure(builder,
                configuration.GetConnectionString(AbpDemoConsts.ConnectionStringName), null);

            return new AbpDemoDbContext(builder.Options);
        }
    }
}
View Code

這樣運行項目, 在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>
View Code

ABP.Net Core使用教程(三)記錄數據庫腳本日誌