zoukankan      html  css  js  c++  java
  • 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($"重写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配置文件中添加配置

    那么最后结果就是在binDebug目录下创建一个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}Logslog.txt”指的就是写到binDebug里面去

    rules标签的name属性指的是logger对象所在的地方

    <targets>
        <target name="logfile" xsi:type="File" fileName="${basedir}Logslog.txt"/>
      </targets>
      <rules>
        <logger name="_201901212.NLog.NLogCommandInterceptor" writeTo="logfile"/>
      </rules>
    View Code

     

    现在起码能够运行,NLog也起作用了,但是很定会有很多问题等着去解决

    后面就具体弄一弄这个NLog,以及和EF搭配实现可用的日志管理功能。

  • 相关阅读:
    交叉编译环境软件搭建
    (C)struct结构体
    (C)字节对齐#pragma pack()
    常用bluetooth协议
    (C/C++)register关键字
    Android学习
    (C)*p++和*++p区别
    java文件末尾追加内容的两种方式
    java1.7集合源码阅读: Stack
    java1.7集合源码阅读: Vector
  • 原文地址:https://www.cnblogs.com/jinshan-go/p/10319100.html
Copyright © 2011-2022 走看看