前言

说点题外话:前几天接连微软老爹发布了 .net core 2.0 / asp.net core 2.0 / ef core 2.0 / .net standard 2.0(此处撒花,不管是否后面如何,但是我们至少看到了微软的努力和成果,||ヽ( ̄▽ ̄)ノミ|Ю,至于说国内环境使然的情况下, 是否能够引来一丝生机般的阳光那就另当别论了!个人还是比较看好,当然这是许许多多.Neter需要一起,才能做到的),其中ef core github wiki 也列出了下季度的计划路线图,详情传送门:https://github.com/aspnet/EntityFrameworkCore/wiki/Roadmap,略微吐槽一下: 咦!这么久了,groupby+lazyload都还没做好,╮(╯▽╰)╭,坐等 ef core 2.1实现,毕竟微软自己都说出口了,还有 netstandard 2.0 API 是比较全了,建议新项目创建 lib 选择使用,这里再说多一句希望ef core新特性也能够在ef 6.x中共享!!!。好了上面说了一通都和我们今天的主题无关,下面我们将开始上期未完成的问题,上期文地址:http://www.cnblogs.com/DjlNet/p/7291865.html,开始我们今天的对EF未完问题的解读.....


声明

本文欢迎转载原文地址:http://www.cnblogs.com/DjlNet/p/7360545.html


正片

注意本文内容一般,可能文中提到的,大部分同学都知道,所以大佬、知晓的园友可绕道(并无不尊之意哈哈),只是博主备份记录以及完成这个系列文。


7、开发者怎么审查EF翻译的SQL语句?

时常在使用EF的途中偶尔觉得怎么访问数据库有点慢呢,这里慢就可能有多种原因,例如:网络延时,应用程序资源争夺,本身数据库响应等等,这里我们仅仅局限于提交到数据库的SQL语句本身执行慢的问题上,那么怎么才能捕获到在生成SQL到提交到数据库执行期间的SQL语句呢,注意:这里下面的部分方法不限于数据库种类,可以拿到SQL语句的。


方法一:使用VS在debug调试环境下的,一般情况在调试界面的右侧会出现如图所示(不同VS版本略有不同,建议使用VS2017):

,其中的筛选器已经默认捕获了ado.net的事件,鼠标点击便可以展开查看事件包含执行的SQL语句,但是你会发现右键没有复制,其实这里直接ctrl+c也可以复制出来选中的信息,但是不能拿到纯粹的SQL语句这点不好且只能在DEBUG模式下才能使用哦,但是如果想快速再不改动项目的情况下用这种方式何尝不是一种好的选择呐。


方法二:使用微软已经默认对 IQueryable 的 ToString 方法重写的实现,拿到的字符串便是纯粹翻译的SQL语句,这里得特别说明一下:不一定拿到的翻译SQL语句在数据库当中能执行,就能在EF正确的体现,这里博主在第二篇博文已经实践过了,所以各位同学得稍稍注意一下。


方法三:使用 DbContext.Database.Log实现,这里EF知道有这方便的需求,所以提供了一个委托类型Action<string>来让开发者自定义处理的Handler,例如:db.Database.Log = Console.WriteLine;将所有关联的SQL和其他信息输出到控制台,注意这里包括了执行的SQL,以及数据库连接的开闭,事务的打开和关闭等等,所以这里需要开发者自己查找自己想看的那部分SQL。


方法四:使用数据库层面的监控工具,例如:数据库是Sqlserver的情况下,即可使用Sql Server Profiler,这个工具顾名思义将是对整个数据库的一个全面监控,更多该工具详情功能介绍参考微软官网把,所以这里肯定会把我们EF所执行的SQL也能监控到了拉,如图所示:,这里便是对上篇文章的查询监控示意图。


方法五:使用社区的第三方EF扩展nuget包,例如:MiniProfiler.EF6,相信它的原理也是在EF提供的API或者横切面实现的呐,这里借用一下官方的贴图示意监控的EF的SQL语句: ,这里我贴出MiniProfiler官方地址:http://miniprofiler.com/,这里还包含了对asp.net mvc 网站的监控,例如一下视图渲染,controller+action 耗时等等,还有一些调用审查日志记录持久化等等,博主将会再下面问题部分展示。


8、开发者怎么监控EF在网站运行情况?

相信大家在使用EF的时候都有过这种想法,但是一般情况下EF都能胜任大部分情况,所有部分开发者都没有稍稍注意到在asp.net mvc 的应用程序中 EF的表现,到这里博主要安利一个监控扩展包了,那就是上面 方法五 提到的 MiniProfiler 全家桶,链接参考上面,其中面对监控这个东西肯定对性能有着一定影响的,所以我们下面的演示将会提供一个可控配置的监控开关来启动或者关闭监控功能,这样就是不是更加灵活了呐!!!接下来,我们一步一步构建可控的网站。


第一步:在你的asp.net mvc应用程序中添加如下的nuget包,相信大家从名字都可以看出来各自nuget包的作用和依赖关系:

  1. <package id="MiniProfiler" version="3.2.0.157" targetFramework="net45" />
  2. <package id="MiniProfiler.EF6" version="3.0.11" targetFramework="net45" />
  3. <package id="MiniProfiler.MVC4" version="3.0.11" targetFramework="net45" />

以及在 Web.config文件AppSettings节点添加Node:<add key="MiniProfilerEnabled" value="true" />,当然这里也可以通过#if DEBUG #endif的方式来实现也是可以的参考链接地址:http://www.cnblogs.com/jiekzou/p/6374726.html,还有在如下的handlers添加miniprofiler自带处理器

  1. <system.webServer>
  2. <handlers>
  3. <add name="MiniProfiler" path="mini-profiler-resources/*" verb="*" type="System.Web.Routing.UrlRoutingModule" resourceType="Unspecified" preCondition="integratedMode" />
  4. </handlers>
  5. </system.webServer>

第二步:在文件夹App_Start,添加如下两个文件:其一MiniProfilerStartUpModule.cs,这里说明一下使用了IHttpModule接口来实现对asp.net框架管道的横切面编程达到把我们监控逻辑注入到流程中去,详情如下注释说明:

  1. public class MiniProfilerStartUpModule : IHttpModule
  2. {
  3. private static bool enable = bool.Parse(System.Configuration.ConfigurationManager.AppSettings["MiniProfilerEnabled"]);
  4. public void Dispose()
  5. {
  6. }
  7. public void Init(HttpApplication context)
  8. {
  9. context.BeginRequest += Context_BeginRequest;
  10. context.EndRequest += Context_EndRequest;
  11. }
  12. private void Context_EndRequest(object sender, EventArgs e)
  13. {
  14. MiniProfiler.Stop();
  15. }
  16. private void Context_BeginRequest(object sender, EventArgs e)
  17. {
  18. if (enable)
  19. {
  20. // 启动miniprofiler监控
  21. MiniProfiler.Start();
  22. }
  23. }
  24. }

其二MiniProfilerActivator.cs,这里使用了 WebActivatorEx nuget包 来控制asp.net应用程序启动的横切面注入编程,以及动态注入asp.net管道使用上述的自定义类:DynamicModuleUtility.RegisterModule(typeof(MiniProfilerStartUpModule));实现拦截,详情如下注释说明:

  1. using StackExchange.Profiling;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Web;
  6. using System.Web.Mvc;
  7. using Microsoft.Web.Infrastructure.DynamicModuleHelper;
  8. // 标记表示应用程序启动之前调用指定类的指定方法
  9. [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(DJLNET.WebMvc.App_Start.MiniProfilerActivator), "Start", Order = 0)]
  10. namespace DJLNET.WebMvc.App_Start
  11. {
  12. public static class MiniProfilerActivator
  13. {
  14. public static void Start()
  15. {
  16. var enable = bool.Parse(System.Configuration.ConfigurationManager.AppSettings["MiniProfilerEnabled"]);
  17. if (enable)
  18. {
  19. // 注入自定义HttpModule
  20. DynamicModuleUtility.RegisterModule(typeof(MiniProfilerStartUpModule));
  21. // 添加监控的actionfiler
  22. GlobalFilters.Filters.Add(new StackExchange.Profiling.Mvc.ProfilingActionFilter());
  23. // 启动ef监控初始化
  24. StackExchange.Profiling.EntityFramework6.MiniProfilerEF6.Initialize();
  25. // 启用显示详情消耗时间信息
  26. MiniProfiler.Settings.PopupShowTimeWithChildren = true;
  27. // 清空原始自带的视图引擎
  28. var viewEngines = ViewEngines.Engines.ToList();
  29. ViewEngines.Engines.Clear();
  30. // 替换为miniprofiler的视图引擎包装器,这样就达到对view渲染时间监控
  31. foreach (var item in viewEngines)
  32. {
  33. var wapper = new StackExchange.Profiling.Mvc.ProfilingViewEngine(item);
  34. ViewEngines.Engines.Add(wapper);
  35. }
  36. }
  37. }
  38. }
  39. }

接着在我们的_Layout.cshtml分别在文件头部添加

  1. @using StackExchange.Profiling;

html body 底部添加如下代码:

  1. @*MiniProfiler配置*@
  2. @MiniProfiler.RenderIncludes()

这样边便可以能够通过miniprofiler的JS注入实现控制实现交互和样式,达到展示性能图表等等


第三步:展示我们的效果图,当然也包括我们的问题中提到的EF的SQL展示等等,这里需要注意一点就是miniprofiler会把它觉得有问题的请求会标记为红色,让开发者注意该请求发生的事情,如下图:









以上便是部分的展示图,请忽略博主的界面和网站设计,这只是用来试验和测试一些方法来用的哈,到这里边是对第八的问题有了一个稍微好的解释和回答了。等等,你以为到这里就算完了嘛,不,还没有,下面我们继续走进EF的一些小知识,请....


EF小知识(加戏篇)

时常在我们基于数据库的应用程序开发得时候,常常需要在SQL查询过程中需要nolock关键字对查询表允许脏读和幻读,那么你想过在EF怎么实现吗,且EF的查询默认是没有开启事务的哦...

其实呢,博主先前也是不知道的呐,但是有Bing、Google还怕什么呢,况且还有Stackoverflow,所以答案就在上面了,多说一句在国内你懂得的环境下面Bing搜索的改版挺赞的哈,先给出链接地址:https://stackoverflow.com/questions/926656/entity-framework-with-nolock,这里总的大部分做法来说是设置上下文环境的事务等级为:System.Transactions.IsolationLevel.ReadUncommitted,链接的方法各异,可以参考使用即可,主要看nolock查询的情况频繁程度和使用场景的多少等等看情况来设置。

例如:可以直接利用在某个特殊查询(什么鬼报表查询)中,直接使用如下方式:

  1. //declare the transaction options
  2. var transactionOptions = new System.Transactions.TransactionOptions();
  3. //set it to read uncommited
  4. transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted;
  5. //create the transaction scope, passing our options in
  6. using (var transactionScope = new System.Transactions.TransactionScope(
  7. System.Transactions.TransactionScopeOption.Required,
  8. transactionOptions)
  9. )
  10. //declare our context
  11. using (var context = new MyEntityConnection())
  12. {
  13. //any reads we do here will also read uncomitted data
  14. //...
  15. //...
  16. //don't forget to complete the transaction scope
  17. transactionScope.Complete();
  18. }

又或者统一在所有EF查询中使用自定义DbCommandInterceptor来控制生成的Command达到with nolock的效果,参考如下:

  1. public class NoLockInterceptor : DbCommandInterceptor
  2. {
  3. private static readonly Regex _tableAliasRegex =
  4. new Regex(@"(?<tableAlias>AS \[Extent\d+\](?! WITH \(NOLOCK\)))",
  5. RegexOptions.Multiline | RegexOptions.IgnoreCase);
  6. [ThreadStatic]
  7. public static bool SuppressNoLock;
  8. public override void ScalarExecuting(DbCommand command,
  9. DbCommandInterceptionContext<object> interceptionContext)
  10. {
  11. if (!SuppressNoLock)
  12. {
  13. command.CommandText =
  14. _tableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)");
  15. }
  16. }
  17. public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
  18. {
  19. if (!SuppressNoLock)
  20. {
  21. command.CommandText =
  22. _tableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)");
  23. }
  24. }
  25. }

然后添加到EF中去DbInterception.Add(new NoLockInterceptor());然后设置启用NoLockInterceptor.SuppressNoLock = true;

其次:这里链接中还提供了一中稍微灵活的方式 postsharp(收费)+ReadUncommitedTransactionScopeAttribute 来实现,想对那些查询应用nolock只需要打上标记就行了,参考如下:

  1. [Serializable]
  2. public class ReadUncommitedTransactionScopeAttribute : MethodInterceptionAspect
  3. {
  4. public override void OnInvoke(MethodInterceptionArgs args)
  5. {
  6. //declare the transaction options
  7. var transactionOptions = new TransactionOptions();
  8. //set it to read uncommited
  9. transactionOptions.IsolationLevel = IsolationLevel.ReadUncommitted;
  10. //create the transaction scope, passing our options in
  11. using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
  12. {
  13. //declare our context
  14. using (var scope = new TransactionScope())
  15. {
  16. args.Proceed();
  17. scope.Complete();
  18. }
  19. }
  20. }
  21. }
  22. [ReadUncommitedTransactionScope()]
  23. public static SomeEntities[] GetSomeEntities()
  24. {
  25. using (var context = new MyEntityConnection())
  26. {
  27. //any reads we do here will also read uncomitted data
  28. //...
  29. //...
  30. }
  31. }

注意这里的是国际友人提供的参考实现方法,博主本身并没有实践,所以酌情使用,自行定夺!!!


这里最后在说一句,Get Record ID in Entity Framework after insert ?回答如下(原文链接:https://stackoverflow.com/questions/16954767/get-record-id-in-entity-framework-after-insert):

总结

至此,我们通过了三篇文章来分析使用EF中遇到的问题和解决手段,也大致了解了EF本身好处和瑕疵吧,也正好这个系列文章也算是有了一个不错的结尾,那么接下博主将在继续研究大家所关心的话题,什么DDD、DI、AOP、IOC、MQ、微服务、分布式、数据一致性等等,以及最近最新的一些的新东西.netcore一系列,例如文中开头所说的一些东西,总之啦对我们来说学习的东西有很多,但是如何下手如何跟进如何凝聚为自身属性,这些都是需要一步一步的走才能长成的吧,但愿与君共勉!期待与你的下次论剑!!

【EntityFramework 6.1.3】个人理解与问题记录(3)的更多相关文章

  1. 【EntityFramework 6.1.3】个人理解与问题记录

    前言 又是一个炎热夏日的晚上,开着空调听着音乐又开始了我们今天的博文.此文并不是ROM工具哪家强之类的引战贴,只是本文自己的一点看法和见解,望前辈看官有望斧正 声明 本文欢迎转载,原文地址:http: ...

  2. 【EntityFramework 6.1.3】个人理解与问题记录(2)

    前言 才看完一季动漫,完结撒花,末将于禁,原为曹家世代赴汤蹈火!想必看过的都会知道这个,等一下要不吐槽一下翻拍的真人版,○( ^皿^)っHiahia-,好了快醒醒改办正事儿了,好的,我们接着上一篇文章 ...

  3. 【CSS选择器】理解汇总和记录

    1.选择器中符号含义汇总(这部分包含了对选择器的通用理解): 1.1.多元素组合符号:(共6个,一个是CSS3的)(适用所有元素:ID组合,类组合,属性组合,标签组合,伪类组合,以及以上所有混合组合) ...

  4. 在EntityFramework(EF)中删除主从表记录

    删除主表:  如果要删除单个的Book对象,由于启用了级联删除,干掉一个Book,它所关联的所有BookReview也一并删除了. (说的简单,如果用Attach方法或者Remove,加修改删除状态, ...

  5. 回调函数透彻理解Java

    http://blog.csdn.net/allen_zhao_2012/article/details/8056665 回调函数透彻理解Java 标签: classjavastringinterfa ...

  6. maximo功能修改(初步理解)

    已接触IBM公司的MAXIMO近三个月,在这时间里自己对maximo也有所了解,今天将自己总结写在这里,方便自己的温习和大家的参考,不足之处还望指出,我一定在第一时间内修改. 今天在公司所做的就是完善 ...

  7. loadrunner throughput(吞吐量)理解

    转自http://www.51testing.com/html/29/n-110129.html   Throughput翻译为吞吐量,按照常规理解网络吞吐量表示在单位时间内通过网卡数据量之和,其中即 ...

  8. 深入理解JS原型链与继承

    我 觉得阅读精彩的文章是提升自己最快的方法,而且我发现人在不同阶段看待同样的东西都会有不同的收获,有一天你看到一本好书或者好的文章,请记得收藏起来, 隔断时间再去看看,我想应该会有很大的收获.其实今天 ...

  9. 关于操作系统中多个fork()会创建几个进程的理解

    最近在看操作系统的书,在讲到用fork()创建子进程时,有些地方一时迷惑,最终理解,特记录下来.如下: //创建一个子进程:#include "csapp.h" int main( ...

随机推荐

  1. 快学Scala之特质

    一个Scala类可以继承多个特质(trait), 特质可能会要求使用它们的类支持某个特定特性, 与Java接口不同, Scala特质可以给出这些特质的缺省实现. 要点如下: Scala中类只能继承一个 ...

  2. Java编程代码性能优化总结

    如果有足够的时间开发.维护代码,这时候就必须考虑每个可以优化的细节了,一个一个细小的优化点累积起来,对于代码的运行效率绝对是有提升的. 代码优化的目标是: 1.减小代码的体积 2.提高代码运行的效率 ...

  3. Kafka基础知识

    1. kafka是一个分布式的消息发布-订阅队列.2. 其中有一些主要的概念: Topic: 就是对放入队列的消息进行分类,分类消息分开储存,比如现在有订单消息和用户投诉消息,则分成订单topic和投 ...

  4. CSS3-loading动画(五)

    CSS3-loading加载动画 在线示例demo:http://liyunpei.xyz/loading.html 之前发了四篇,二十二个效果,今天再分享六个效果,总计二十八个效果. 二十三.效果二 ...

  5. JavaSE中Map框架学习笔记

    前言:最近几天都在生病,退烧之后身体虚弱.头疼.在床上躺了几天,什么事情都干不了.接下来这段时间,要好好加快进度才好. 前面用了三篇文章的篇幅学习了Collection框架的相关内容,而Map框架相对 ...

  6. T4 代码生成 Demo (抽奖程序)

    参考自这位大狮的:  https://github.com/Pencroff/Dapper-DAL/blob/master/Dapper-DAL/Models/ModelGenerator.tt 项目 ...

  7. 走进安卓的重灾区----video

    html5的video已经出来很久了.在ios上使用基本上没什么毛病,但是安卓下就是一个重灾区了,各种体验差.这几天搞了安卓的兼容,简直是要吐血.所以特意总结了一些强势的坑点. 先看一下常用的一些属性 ...

  8. Jquery table元素操作-创建|数据填充|重置|隐藏行

    1.Jquery创建表格 /** * 创建表格 * @param label 标题 json格式,数据结构见附录1 * @param data 数据 json格式,数据结构见附录1 * @param ...

  9. RabbitMQ 知识总结

    RabbitMQ知识总结 AMQP协议 AMQP协议是一个提供统一消息服务的应用层标准协议,并不会受到客户端/中间件不同产品.不同开发语言等条件的影响.RabbitMQ则是基于该协议实现的. 举个例子 ...

  10. Java 9 揭秘(19. 平台和JVM日志)

    Tips 做一个终身学习的人. 在这章中,主要介绍以下内容: 新的平台日志(logging)API JVM日志的命令行选项 JDK 9已经对平台类(JDK类)和JVM组件的日志系统进行了大整. 有一个 ...