1. 程式人生 > >EF6學習筆記二十一:格式化日誌輸出

EF6學習筆記二十一:格式化日誌輸出

exec https edi 進行 mman sel 能夠 database container

要專業系統地學習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($
"重寫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); } }
View Code

在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學習筆記二十一:格式化日誌輸出