EF6學習筆記二十一:格式化日誌輸出
要專業系統地學習EF推薦《你必須掌握的Entity Framework 6.x與Core 2.0》。這本書作者(汪鵬,Jeffcky)的博客:https://www.cnblogs.com/CreateMyself/
格式化日誌輸出
上次我們知道了利用ctx.Database.Log來進行簡單的日誌打印,還是很有幫助的。
那麽它其實是繼承自DatabaseLogFormatter,那麽我們可以寫一個派生自DatabaseLogFormatter這個類,來實現更多的自定義操作
實現步驟
1 寫一個派生自DatabaseLogFormatter的類
2.在EF中進行註冊
又到了學英語的時候,看一下DatabaseLogFormatter
我來重寫LogCommad 和Closing方法,因為對裏面的東西都不熟,所以我都打印看一下
public class DBlogFormatter : DatabaseLogFormatter { public DBlogFormatter(DbContext context, Action<string> writeAction) : base(context, writeAction) { } public override void LogCommand<TResult>(DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext) { Write($View Code"重寫LogCommand:記錄將要執行的命令:command.CommandText:{command.CommandText}{Environment.NewLine}" + $"command.CommandTimeout:{command.CommandTimeout}{Environment.NewLine}" + $"command.CommandType:{command.CommandType}{Environment.NewLine}" + $"command.Connection:{command.Connection}{Environment.NewLine}" + $"command.Container:{command.Container}{Environment.NewLine}" + $"command.Parameters:{command.Parameters}{Environment.NewLine}" + $"command.Site:{command.Site}{Environment.NewLine}" + $"command.ToString():{command.ToString()}{Environment.NewLine}" + $"command.Transaction:{command.Transaction}{Environment.NewLine}" + $"command.UpdateRowSource:{command.UpdatedRowSource}{Environment.NewLine}"); } public override void Closing(DbConnection connection, DbConnectionInterceptionContext interceptionContext) { Write($"重寫Closing:{Environment.NewLine}" + $"connection.ConnectinoString:{connection.ConnectionString}{Environment.NewLine}" + $"connection.ConnectionTimeout:{connection.ConnectionTimeout}{Environment.NewLine}" + $"connection.Container:{connection.Container}{Environment.NewLine}" + $"connection.Database:{connection.Database}{Environment.NewLine}" + $"connection.DataSource:{connection.DataSource}{Environment.NewLine}" + $"connection.ServerVersion:{connection.ServerVersion}{Environment.NewLine}" + $"connection.Site:{connection.Site}{Environment.NewLine}"); base.Closing(connection, interceptionContext); } }
在EF中註冊配置
public class DBContextConfiguration:DbConfiguration { public DBContextConfiguration() { SetDatabaseLogFormatter((context,action) => new DBlogFormatter(context,action)); } }View Code
最後看看,在我們自定義之前和之後打印的比較
差不多就是這樣了,行吧,我其實覺得ctx.Database.Log對我來說已經夠用了。那麽作者又說到了攔截和日誌框架的使用
攔截+NLog日誌框架
要實現攔截就要繼承IDbInterceptor,當EF調用ExceuteNonQuery、ExecuteScalar、ExecuteReader(CURD)等相關方法時,在IDbInterceptor上定義的方法都會被調用。
該接口存在的最終意義是為了追蹤SQL和格式化輸出SQL
我們上面弄得那個DatabaseLogFormatter,它就繼承了IDbInterceptor
弄起來很簡單,和上面差不多,只不過我們現在加上一個NLog日誌框架來配合使用
步驟,1.下載Nlog、NLog.config
2.寫一個派生自IDbinterceptor的類,將攔截信息使用NLog寫入
3.在EF中註冊配置
4、NLog配置文件中添加配置
那麽最後結果就是在bin\Debug目錄下創建一個Logs文件夾,裏面有記錄的日誌
namespace _201901212.NLog { public class NLogCommandInterceptor : IDbCommandInterceptor { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { LogIfError(command,interceptionContext); } public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { LogIfNonAsync(command,interceptionContext); } public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { LogIfError(command,interceptionContext); } public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { LogIfNonAsync(command, interceptionContext); } public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { LogIfError(command, interceptionContext); } public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { LogIfNonAsync(command,interceptionContext); } private void LogIfNonAsync<TResult>(DbCommand command,DbCommandInterceptionContext<TResult> interceptionContext) { if (!interceptionContext.IsAsync) { Console.WriteLine(Logger.Name); Console.WriteLine($"張四海{Logger}"); Logger.Warn("Non-async command used:{0}",command.CommandText); } } private void LogIfError<TResult>(DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext) { if (interceptionContext.Exception != null) { Logger.Error("Command {0} failed with exception {1}",command.CommandText,interceptionContext.Exception); } } }View Code
public class DBContextConfiguration:DbConfiguration { public DBContextConfiguration() { // 添加攔截器 DbInterception.Add(new NLogCommandInterceptor()); } }View Code
targets變遷 filename屬性指的是將日誌寫到哪裏去,我這裏寫的“${basedir}\Logs\log.txt”指的就是寫到bin\Debug裏面去
rules標簽的name屬性指的是logger對象所在的地方
<targets> <target name="logfile" xsi:type="File" fileName="${basedir}\Logs\log.txt"/> </targets> <rules> <logger name="_201901212.NLog.NLogCommandInterceptor" writeTo="logfile"/> </rules>View Code
現在起碼能夠運行,NLog也起作用了,但是很定會有很多問題等著去解決
後面就具體弄一弄這個NLog,以及和EF搭配實現可用的日誌管理功能。
EF6學習筆記二十一:格式化日誌輸出