zoukankan      html  css  js  c++  java
  • EntityFramework6.0的Sql读写分离拦截器 和 MVC的 Action拦截器 对比

    EF的DbCommandInterceptor类 拦截:

    EF6.1也出来不少日子了,6.1相比6.0有个很大的特点就是新增了System.Data.Entity.Infrastructure.Interception 命名空间,此命名空间下的对象可以允许我们更加方便的了解到EF运行时的一些信息,当然我们最想看的还是EF生成的Sql语句,话不多讲,开始干吧;

    class EFIntercepterLogging : DbCommandInterceptor
        {
            private readonly Stopwatch _stopwatch = new Stopwatch();
            public override void ScalarExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
            {
                base.ScalarExecuting(command, interceptionContext);
                _stopwatch.Restart();
            }
            public override void ScalarExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
            {
                _stopwatch.Stop();
                if (interceptionContext.Exception != null)
                {
                    Trace.TraceError("Exception:{1} 
     --> Error executing command: {0}", command.CommandText, interceptionContext.Exception.ToString());
                }
                else
                {
                    Trace.TraceInformation("
    执行时间:{0} 毫秒
    -->ScalarExecuted.Command:{1}
    ", _stopwatch.ElapsedMilliseconds, command.CommandText);
                }
                base.ScalarExecuted(command, interceptionContext);
            }
            public override void NonQueryExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
            {
                base.NonQueryExecuting(command, interceptionContext);
                _stopwatch.Restart();
            }
            public override void NonQueryExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
            {
                _stopwatch.Stop();
                if (interceptionContext.Exception != null)
                {
                    Trace.TraceError("Exception:{1} 
     --> Error executing command:
     {0}", command.CommandText, interceptionContext.Exception.ToString());
                }
                else
                {
                    Trace.TraceInformation("
    执行时间:{0} 毫秒
    -->NonQueryExecuted.Command:
    {1}", _stopwatch.ElapsedMilliseconds, command.CommandText);
                }
                base.NonQueryExecuted(command, interceptionContext);
            }
            public override void ReaderExecuting(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
            {
                base.ReaderExecuting(command, interceptionContext);
                _stopwatch.Restart();
            }
            public override void ReaderExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<System.Data.Common.DbDataReader> interceptionContext)
            {
                _stopwatch.Stop();
                if (interceptionContext.Exception != null)
                {
                    Trace.TraceError("Exception:{1} 
     --> Error executing command:
     {0}", command.CommandText, interceptionContext.Exception.ToString());
                }
                else
                {
                    Trace.TraceInformation("
    执行时间:{0} 毫秒 
     -->ReaderExecuted.Command:
    {1}", _stopwatch.ElapsedMilliseconds, command.CommandText);
                }
                base.ReaderExecuted(command, interceptionContext);
            }
        }
    View Code

    上面这段代码需要命名空间:

    using System.Data.Entity.Infrastructure.Interception;
    using System.Diagnostics;

    从方法名我们可以看出大致就三类:读取类的sql,[Reader],非读取类的sql,[NonQuery],还有[Scalar],这类用的比较少,跟原始的ADO.NET命令类型基本一样,不多讲.每个sql语句类型的方法都有执行前Executing,执行后Executed,从命名上我们就可以看出AOP的身影哈,接下来看如何使用它...

    嗯,对没错,就是这么简单,当然你还可以把红线里那句代码放在Global文件里.

    我们看看运行效果


    个人感觉是比用什么插件,第三方类库,SqlProfile什么的方便点点,用博客园的Google搜索了一下,貌似没发现其他园友写这个方法,可能是太简单了,都不愿意写,还是麻烦推荐一下让更多的园友看到!

    -------

    MVC拦截器:

    MVC过滤器 OnActionExecuting() 在过滤器中获取触发控制器,Action 等

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.Mvc;  
    using System.Web.Routing;  
      
    namespace FB.CMS.MvcSite  
    {  
        public class RouteConfig  
        {  
            public static void RegisterRoutes(RouteCollection routes)  
            {  
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  
      
                routes.MapRoute(  
                    name: "Default",  
                    url: "{controller}/{action}/{id}",  
                    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },  
                    namespaces: new string[] { "FB.CMS.MvcSite.Areas.admin.Controllers" }//项目中如果存在多个Home控制器,需要设定Home控制器的名称空间  
      
                ).DataTokens.Add("area", "admin") //.DataTokens.Add("area","admin")就表示将区域里的admin区域的Home控制器的Index视图设为默认启动项  
                ;  
            }  
        }  
    }  
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.Mvc;  
      
    namespace MVC过滤器.Filters  
    {  
        //自定义一个过滤器  
        [MyActionFilter]  
        public class MyActionFilterAttribute:ActionFilterAttribute  
        {  
            //重写OnActionExecuting方法  
            public override void OnActionExecuting(ActionExecutingContext filterContext)  
            {  
                //我们先来了解一下这个filterContext参数:我们知道OnActionExecuting方法是在Action执行之前会被触发执行的一个方法,那就意味着,将来我在这里面写代码,想要知道你这一个OnActionExecuting方法到底是由那一个Action被调用的时候触发的 (因为所有的action方法被执行的时候都会触发OnActionExecuting这个过滤器方法,所以我就像要知道到底是哪个action被执行的时候触发的这个OnActionExecuting方法)  
      
                //获取触发当前方法(OnActionExecuting)的Action名字(即:哪个Action方法被执行的时候触发的OnActionExecuting(ActionExecutingContext filterContext))  
                string actionName = filterContext.ActionDescriptor.ActionName;  
      
                //获取触发当前方法的的Action所在的控制器名字  
                string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;  
      
                //获取触发当前方法的Action方法的所有参数(因为参数可能有多个,所以它是一个集合,它的返回值类型是IDictionary<string ,object> 下面为了好看,用var替代)  
                var paramss = filterContext.ActionParameters;  
      
                string str = "";  
                if (paramss.Any()) //Any是判断这个集合是否包含任何元素,如果包含元素返回true,否则返回false  
                {  
                    foreach (var key in paramss.Keys) //遍历它的键;(因为我们要获取的是参数的名称s,所以遍历键)  
                    {  
                        str = key + "的值是" + paramss[key];  //paramss[key] 是key的值  
                    }  
                }  
      
                  
      
                //获取当前请求的上下文  
                filterContext.HttpContext.Response.Write("你好,我也好");  
      
      
                //将触发当前方法的这个Action方法的返回结果视图换成一个JsonResult  ( filterContext.Result的返回类型就是JsonResult)  
      
                //filterContext.Result:获取或设置由操作方法返回的结果。(既然是获取或者设置Action方法的返回结果,那么我们就可以在这里篡改触发当前方法的那个Action方法的返回结果  
      
                //例如:触发当前方法的Action方法是这个:public ActionResult Add(){return Content("中国");} 这个Action方法的返回值是一个"中国"文本  那么我们在这里可以通过filterContext.Result来篡改它的返回值。比如这我给他返回一个json  
      
                JsonResult json=new JsonResult();  
                json.Data=new { status="1",message="OK"};  
                json.JsonRequestBehavior = JsonRequestBehavior.AllowGet;  
      
                filterContext.Result = json;  
      
      
                  
            //假设我们在MVC项目中添加一个名字为admin的区域,然后再区域下添加一个Home控制器,然后添加一个Index视图。  
            //那现在我们访问这个视图的路径就是:http://localhost:5219/admin/home/index  
                //获取区域  
                var area = filterContext.RouteData.DataTokens;//MVC可以有区域的,这里就是负责存放区域的  
      
                //获取区域名称  
                var areaName = area["area"];//这个["area"]是写死了的。你根据["area"]就可以取到区域名称,因为区域的key固定就是area  所以这里areaName的值为admin  
      
      
                //RouteData  
                var rd = filterContext.RouteData; //在这里面可以获取控制名称,ation名称,参数名称  
      
                var controlName = rd.Values["Controller"].ToString();  
                var actName = rd.Values["Action"].ToString();  
                  
                 
          
                  
                  
            }  
        }  
    }  
  • 相关阅读:
    开源.net 混淆器ConfuserEx介绍
    k8s删除namespace失败,状态Terminating解决方案
    java get all threadlocal from thread
    mysql查看索引的大小
    InnoDB一定会在索引中加上主键吗?
    全链路追踪traceId,ThreadLocal与ExecutorService
    redis 批量删除keys
    shell逐行读取excel并执行sql
    Is it possible to create @Around Aspect for feign.Client
    Spring Boot后台启动不打印nohup.out
  • 原文地址:https://www.cnblogs.com/x-poior/p/6099817.html
Copyright © 2011-2022 走看看