分享一个 .NET 通过监听器拦截 EF 消息写日志的详细例子

image

前言

EF 开发效率确实很高也很便捷,但当它发生错误时,也挺让人头疼的,为什么?因为 EF 就像是一个黑盒子,一切全被封装起来,出错的时候很难定位原因,如果能够知道并打印 EF 生成的 SQL 语句,对于定位 EF 错误,就很有帮助。

程序员的才智是无限的,虽然 EF 有这个那个的问题,但程序员却总比这些问题多一个办法。

下面分享一个 .NET 通过监听器拦截 EF 消息写日志的详细例子。

Step By Step 步骤

  1. 创建自定义监听器类,拦截 EF 的命令执行事件(留意注释

    /// <summary>
    /// 监听并写 EF 生成的 SQL 到日志
    /// </summary>
    public class EFIntercepterLogging : IDbCommandInterceptor
    {/// <summary>/// 实现接口的 NonQueryExecuting 方法/// </summary>/// <param name="command"></param>/// <param name="interceptionContext"></param>public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext){LogWhenExecuting(command, interceptionContext);}/// <summary>/// 实现接口的 NonQueryExecuted 方法/// </summary>/// <param name="command"></param>/// <param name="interceptionContext"></param>public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext){LogIfError(command, interceptionContext);}/// <summary>/// 实现接口的 ReaderExecuting 方法/// </summary>/// <param name="command"></param>/// <param name="interceptionContext"></param>public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext){LogWhenExecuting(command, interceptionContext);}/// <summary>/// 实现接口的 ReaderExecuted 方法/// </summary>/// <param name="command"></param>/// <param name="interceptionContext"></param>public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext){LogIfError(command, interceptionContext);}/// <summary>/// 实现接口的 ScalarExecuting 方法/// </summary>/// <param name="command"></param>/// <param name="interceptionContext"></param>public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext){LogWhenExecuting(command, interceptionContext);}/// <summary>/// 实现接口的 ScalarExecuted 方法/// </summary>/// <param name="command"></param>/// <param name="interceptionContext"></param>public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext){LogIfError(command, interceptionContext);}/// <summary>/// 写 EF 执行中的 SQL 日志,Debug 级别,用在 Executing 方法/// </summary>/// <typeparam name="TResult"></typeparam>/// <param name="command"></param>/// <param name="interceptionContext"></param>private void LogWhenExecuting<TResult>(DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext){Logger.DebugFormat("Executing the following SQL: [{0}]", command.CommandText);}/// <summary>/// 出现异常时写日志到 Log4net/// </summary>/// <typeparam name="TResult"></typeparam>/// <param name="command"></param>/// <param name="interceptionContext"></param>private void LogIfError<TResult>(DbCommand command, DbCommandInterceptionContext<TResult> interceptionContext){if (interceptionContext.Exception != null){var errMsg = new StringBuilder(16);errMsg.AppendLine("Error occurred when executing the following SQL: ");errMsg.AppendLine(command.CommandText);foreach (DbParameter param in command.Parameters){errMsg.AppendLine($"ParameterName:[{param.ParameterName}] -- DbType:[{param.DbType}] -- Value:[{param.Value}]");}Logger.Error(errMsg, interceptionContext.Exception);}}
    }
    
  2. 在 Global.asax 中的 Application_Start 方法注册监听器

    protected void Application_Start()
    {AreaRegistration.RegisterAllAreas();FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);RouteConfig.RegisterRoutes(RouteTable.Routes);BundleConfig.RegisterBundles(BundleTable.Bundles);//autofac注册AutofacConfig.RegisterConfig();//注册 EF log 监听器DbInterception.Add(new EFIntercepterLogging());
    }
    
  3. 这样就实现了监听器拦截 EF 消息写日志的功能,当运行程序执行 EF 语句时,就会自动将 EF 生成的 SQL 写到日志文件中

总结

通过实现自定义监听器类并注册监听器,可以跟踪和记录 EF 的操作和事件,在开发过程中更好地了解和调试 EF 的行为,不失为排查 EF 问题和优化 EF 性能的一个好方法。

我是老杨,一个奋斗在一线的资深研发老鸟,让我们一起聊聊技术,聊聊程序人生,共同学习,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/870654.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Memcached内存告急:深度解析与实战优化

标题&#xff1a;Memcached内存告急&#xff1a;深度解析与实战优化 在现代的动态Web应用中&#xff0c;Memcached作为一项关键的缓存技术&#xff0c;以其卓越的性能和简便的部署赢得了开发者的青睐。然而&#xff0c;随着数据量的激增和访问频率的提高&#xff0c;Memcached…

记录些Redis题集(1)

为什么Redis要有淘汰机制&#xff1f; 淘汰机制的存在是必要的&#xff0c;因为Redis是一种基于内存的数据库&#xff0c;所有数据都存储在内存中。然而&#xff0c;内存资源是有限的。在Redis的配置文件redis.conf中&#xff0c;有一个关键的配置项&#xff1a; # maxmemory…

Go语言入门之Map详解

Go语言入门之Map详解 1.基础定义 map是一个无序的&#xff0c;k-v键值对格式的集合 &#xff08;1&#xff09;特点 类型特点&#xff1a;map为引用类型&#xff0c;所以在函数中更新value值会永久改变顺序特点&#xff1a;map的遍历是无序的&#xff0c;因为底层是哈希表&am…

零基础学python(二)

1. 字典 字典的创建 最常见的创建方式&#xff1a; d {"k1": "v1", "k2": "v2"} 再向字典中添加一对键值&#xff1a; d["k3"] "v3" 字典还可以用dict()创建&#xff0c;这种方式中&#xff0c;键是不加引…

【Unity2D 2022:UI】制作主菜单

一、创建主菜单游戏场景 1. 在Scenes文件夹中新建一个游戏场景Main Menu 2. 为场景添加背景 &#xff08;1&#xff09;创建画布Canvas &#xff08;2&#xff09;在Canvas中创建新的空游戏物体Main Menu &#xff08;3&#xff09;在Main Menu中新建一个图像游戏物体Backgrou…

GDB调试

GDB调试 一 调试准备二 启动和退出gdb2.1 启动gdb2.2 命令行传参2.3 gdb中启动程序2.4 退出gdb 三 查看代码3.1 当前文件3.2 切换文件3.3 设置显示的行数 四 断点操作4.1 设置断点4.2 查看断点4.3 删除断点4.4 设置断点状态 五 调试命令5.1 继续运行gdb5.2 手动打印信息5.2.1 打…

无人机之机身保养

一、外观检查 1、检查机器表面整洁无划痕、无针孔凹陷擦伤、畸变等损坏情况&#xff1b; 2、晃动机身&#xff0c;仔细听机身内部有无松动零件或者螺丝在机身内部。 二、桨叶检查 1、有无裂痕、磨损、变形等缺陷&#xff0c;如有明显缺陷建议更换&#xff1b; 2、卡扣、紧…

C++函数模板学习

函数模板是C中的一个强大特性&#xff0c;允许编写通用函数来处理不同的数据类型。学习函数模板有助于理解泛型编程的概念&#xff0c;提高代码的可重用性和可维护性。以下是一些学习函数模板时可以关注的方面&#xff1a; 1. 模板的基本概念 模板定义&#xff1a;了解如何定义…

WebSocket、socket.io-client

WebSocket WebSocket 是一种网络通信协议&#xff0c;它提供了一个在单个长期持久的 TCP 连接上进行全双工&#xff08;full-duplex&#xff09;通信的通道。 WebSocket 允许客户端和服务器之间进行双向的数据交换&#xff0c;这意味着服务器可以主动向客户端推送数据&#x…

Animate软件基础:图层的基本用法

图层作为Animate软件中比较重要的功能&#xff0c;需要对其使用方法和作用理解充分&#xff0c;并熟练操作才可以更好的用来制作内容。 图层相关的功能和用法如下&#xff1a; 图层可以帮助在文档中组织插图。 可以在一个图层上绘制和编辑对象&#xff0c;而不会影响其他图层…

排座椅【详细代码题解】

[NOIP2008 普及组] 排座椅 题目描述 上课的时候总会有一些同学和前后左右的人交头接耳&#xff0c;这是令小学班主任十分头疼的一件事情。不过&#xff0c;班主任小雪发现了一些有趣的现象&#xff0c;当同学们的座次确定下来之后&#xff0c;只有有限的 D D D 对同学上课时…

USB转RS485+RS232+TTL串口电路

USB转RS485RS232TTL电路 USB转RS485RS232TTL电路如下图所示&#xff0c;可实现USB转RS485RS232TTL串口&#xff0c;一个电路模块即可实现电路调试过程中用到常用接口。 电路模块上留有2.54MM单排针接口和接线端子两种接线方式&#xff0c;可接线和跳线。电路模块同时有5V和3.3V…

Postman脚本炼金术:高级数据处理的秘籍

&#x1f916; Postman脚本炼金术&#xff1a;高级数据处理的秘籍 Postman不仅是API测试的强大工具&#xff0c;它的脚本功能同样能够在数据处理方面大放异彩。无论是在请求之前设置环境&#xff0c;还是测试后验证结果&#xff0c;Postman的脚本都能提供强大的数据处理能力。…

开源浏览器引擎对比与适用场景:WebKit、Chrome、Gecko

WebKit与Chrome的Blink引擎对比 起源与关系&#xff1a; WebKit最初由苹果公司开发&#xff0c;用于Safari浏览器。后来&#xff0c;WebKit逐渐成为一个独立的开源项目&#xff0c;被多个浏览器厂商采用。Blink是Google基于WebKit项目分支出来的一个浏览器引擎&#xff0c;用于…

文献翻译与阅读《Integration Approaches for Heterogeneous Big Data: A Survey》

CYBERNETICS AND INFORMATION TECHNOLOGIES’24 论文原文下载地址&#xff1a;原文下载 目录 1 引言 2 大数据概述 3 大数据的异构性 4 讨论整合方法 4.1 大数据仓库&#xff08;BDW&#xff09; 4.2 大数据联盟&#xff08;BDF&#xff09; 5 DW 和 DF 方法的比较、分…

C++入门基础题:数组元素逆序(C++版互换方式)

1.题目&#xff1a; 数组元素逆置案例描述: 请声明一个5个元素的数组&#xff0c;并且将元素逆置. (如原数组元素为:1,3,2,5,4;逆置后输出结果为:4,5,2,3,1) 2.图解思路&#xff1a; 3.代码演示&#xff1a; #include<iostream>using namespace std;int main(){int a…

常见颜色汇总

目录 常见的8种颜色&#xff1a; 常见的32种颜色&#xff1a; 常见的8种颜色&#xff1a; colors_8 [(0, 0, 0), # Black(255, 255, 255), # White(255, 0, 0), # Red(0, 255, 0), # Lime(0, 0, 255), # Blue(255, 255, 0), # Yellow(0, 255, 255), …

[k8s源码]1.client-go集群外部署

client-go是由k8s发布且维护的专门用于开发者和kubernetes交互的客户端库。它支持对k8s资源的CRUD操作&#xff08;create、read、update、delete&#xff09;&#xff0c;事件监听和处理&#xff0c;访问kubernetes集群的上下文和配置。 client go是独立于kubernetes集群之外…

Rust vs Go: 特点与应用场景分析

目录 介绍Rust的特点Go的特点Rust的应用场景Go的应用场景总结 介绍 Rust和Go&#xff08;Golang&#xff09;是现代编程语言中两个非常流行的选择。凭借各自的独特优势和广泛的应用场景&#xff0c;吸引了大量开发者的关注。本文将详细介绍Rust和Go的特点&#xff0c;并探讨它…

[Linux][Shell][Shell逻辑控制]详细讲解

目录 1.if 判断1.if-then2.if-then-else3.elif4.case5.实际上手 2.条件测试0.事前说明1.test 命令2.[]3.双括号1.(())2.[[]] 4.实际上手 3.循环1.for2.while3.until命令4.控制循环1.break2.continue 5.处理循环的输出 1.if 判断 1.if-then 语法&#xff1a;if command thenco…