ABP.Net Core使用教程(三)記錄資料庫指令碼日誌
阿新 • • 發佈:2018-12-06
可以跟蹤資料庫指令碼能很好的幫助我們理解ABP , SQL Server Profiler當然是很好的工具 , 好像MySQL沒有這麼方便的工具
這裡我們討論用日誌記錄的方法
1, 首先我們建兩個類來記錄EFCore產生的指令碼日誌
EFLogger.cs
using Microsoft.Extensions.Logging; using System; namespace AbpDemo.EntityFrameworkCore.Logger { public class EFLogger : ILogger {View Codepublic 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,日誌級別為Informationvar 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; } }
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