ABP.Net Core使用教程(三)记录数据库脚本日志
可以跟踪数据库脚本能很好的帮助我们理解ABP , SQL Server Profiler当然是很好的工具 , 好像MySQL没有这么方便的工具
这里我们讨论用日志记录的方法
1, 首先我们建两个类来记录EFCore产生的脚本日志
EFLogger.cs
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; } }
EfLoggerProvider.cs
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() { } } }
2, 修改AbpDemoDbContextConfigurer.cs
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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(); //日志显示脚本参数 } } }
3, 修改AbpDemoEntityFrameworkModule.cs 构建EfLoggerProvider类并提供给配置类使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; } } } }
4, 修复AbpDemoDbContextFactory.cs 的报错,传入空日志类就可以了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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); } } }
这样运行项目, 在Logs.txt中就会显示所有的数据库脚本了
我对日志进行了分类存放, 下面是参考的 log4net.config
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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>