你必须知道的EF知识和经验

注意:以下内容如果没有特别申明,默认使用的EF6.0版本,code first模式

推荐MiniProfiler插件

工欲善其事,必先利其器。

我们使用EF和在很大程度提高了开发速度,不过随之带来的是很多性能低下的写法和生成不太高效的sql。

虽然我们可以使用SQL Server Profiler来监控执行的sql,不过个人觉得实属麻烦,每次需要打开、过滤、清除、关闭。

在这里强烈推荐一个插件MiniProfiler。实时监控页面请求对应执行的sql语句、执行时间。简单、方便、针对性强。

如图:(具体使用和介绍请移步)

数据准备

新建实体:Score(成绩分数表)、Student(学生表)、Teacher(老师表)

后面会给出demo代码下载链接

foreach循环的陷进 

1.关于延迟加载

请看上图红框。为什么StudentId有值,而Studet为null?因为使用code first,需要设置导航属性为virtual,才会加载延迟加载数据。

2.关于在循环中访问导航属性的异常处理(接着上面,加上virtual后会报以下异常

"已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭。"

解决方案:

  • 方案1、设定ConnectionString加上MultipleActiveResultSets=true,但只适用于SQL 2005以后的版本

  • 方案2、或者先读出放置在List中

3.以上两点仅为热身,我们说的陷阱才刚刚开始!

然后我们点击打开MiniProfiler工具(不要被吓到

解决方案:使用Include显示连接查询(注意:需要手动导入using System.Data.Entity 不然Include只能传表名字符串)。

再看MiniProfiler的监控(瞬间101条sql变成了1条,这其中的性能可想而知。

AutoMapper工具

上面我们通过Include显示的执行表的连接查询显然是不错的,但还不够。如果我们只需要查询数据的某些字段呢,上面查询所有字段岂不是很浪费内存存储空间和应用程序与数据库数据传输带宽。

我们可以:

对应监控到的sql:

我们看到生成的sql,查询的字段少了很多。只有我们显示列出来字段的和一个StudentId,StudentId用来连接查询条件的。

是的,这样的方式很不错。可是有没有什么更好的方案或方式呢?答案是肯定的。(不然,也不会在这里屁话了。)如果表字段非常多,我们需要使用的字段也非常多,导航属性也非常多的时候,这样的手动映射就显得不那么好看了。那么接下来我们开始介绍使用AutoMapper来完成映射:

注意:首先需要NuGet下载AutoMapper。

我们看到上面查询语句没有一个个的手动映射,而映射都是独立配置了。其中CreateMap应该是要写到Global.asax文件里面的。其实也就是分离了映射部分,清晰了查询语句。细心的同学可能注意到了,这种方式还免去了主动Include

我们看到了生成的sql和前面有些许不同,但只生成了一条sql,并且结果也是正确的。(其实就是多了一条CASE WHEN ([Extent2].[Id] IS NOT NULL) THEN 1 END AS [C1]。看起来这条语句并没有什么实际意义,然而这是AutoMapper生成的sql,同时我也表示不理解为什么和EF生成的不同)

这样做的好处?

  1. 避免在循环中访问导航属性多次执行sql语句。

  2. 避免了查询语句中太多的手动映射,影响代码的阅读。

关于AutoMapper的其他一些资料:

http://www.cnblogs.com/xishuai/p/3712361.html

http://www.cnblogs.com/xishuai/p/3700052.html

http://www.cnblogs.com/farb/p/AutoMapperContent.html

联表查询统计

要求:查询前100个学生考试类型(“模拟考试”、“正式考试”)、考试次数、语文平均分、学生姓名,且考试次数大于等于3次。(按考试类型分类统计

代码如下:

看到这样的代码,我第一反应是惨了。又在循环执行sql了。监控如下:

其实,我们只需要稍微改动就把101条sql变成1条,如下:

马上变1条。

我们打开查看详细的sql语句

发现这仅仅只是查询结果集合而已,其中的按考试类型来统计是程序拿到所有数据后在计算的(而不是在数据库内计算,然后直接返回结果),这样同样是浪费了数据库查询数据传输。

关于连接查询分组统计我们可以使用SelectMany,如下:

监控sql如下:(是不是简洁多了呢?

关于SelectMany资料:

http://www.cnblogs.com/lifepoem/archive/2011/11/18/2253579.html

http://www.cnblogs.com/heyuquan/p/Linq-to-Objects.html

性能提升之AsNonUnicode

监控到的sql

我们看到EF正常情况生成的sql会在前面带上“N”,如果我们加上DbFunctions.AsNonUnicode生成的sql是没有“N”的,当你发现带上“N”的sql比没有带“N”的 sql查询速度慢很多的时候那就知道该怎么办。

以前用oracle的时候带不带“N”查询效率差别特别明显,今天用sql server测试并没有发现什么差别。还有我发现EF6会根据数据库中是nvarchar的时候才会生成带“N”的sql,oracle数据库没测试,有兴趣的同学可以测试下

性能提升之AsNoTracking

我们看生成的sql

sql是生成的一模一样,但是执行时间却是4.8倍。原因仅仅只是第一条EF语句多加了一个AsNoTracking。

AsNoTracking干什么的呢?无跟踪查询而已,也就是说查询出来的对象不能直接做修改。所以,我们在做数据集合查询显示,而又不需要对集合修改并更新到数据库的时候,一定不要忘记加上AsNoTracking。

多字段组合排序(字符串)

要求:查询名字里面带有“张三”的学生,先按名字排序,再按年龄排序。

咦,不对啊。按名字排序被年龄排序覆盖了。我们应该用ThenBy来组合排序。

不错不错,正是我们想要的效果。如果你不想用ThenBy,且都是升序的话,我们也可以:

生成的sql是一样的。与OrderBy、ThenBy对应的降序有OrderByDescending、ThenByDescending。

看似好像很完美了。其实不然,我们大多数情况排序是动态的。比如,我们会更加前端页面不同的操作要求不同字段的不同排序。那我们后台应该怎么做呢?

当然,这样完成是没问题的,只要你愿意。可以这么多可能的判断有没有感觉非常SB?是的,我们当然有更好的解决方案。要是OrderBy可以直接传字符串???

解决方案:

  1. guget下载System.Linq.Dynamic 

  2. 导入System.Linq.Dynamic命名空间

  3. 编写OrderBy的扩展方法

然后上面又长又臭的代码可以写成:

我们看下生成的sql:

和我们想要的效果完全符合,是不是感觉美美哒!!

lamdba条件组合

要求:根据不同情况查询,可能情况

  1. 查询name=“张三” 的所有学生

  2. 查询name=“张三” 或者 age=18的所有学生

实现代码:

是不是味到了同样的臭味。下面我们来灵活组装Lamdba条件。

解决方案:

这段代码我也是从网上偷的,具体链接找不到了。

然后我们的代码可以写成:

有没有美美哒一点。然后我们看看生成的sql是否正确:

EF的预热

http://www.cnblogs.com/dudu/p/entity-framework-warm-up.html

count(*)被你用坏了吗(Any的用法)

要求:查询是否存在名字为“张三”的学生。(你的代码会怎样写呢?

第一种?第二种?第三种?呵呵,我以前就是使用的第一种,然后有人说“你count被你用坏了”,后来我想了想了怎么就被我用坏了呢?直到对比了这三个语句的性能后我知道了。

性能之差竟有三百多倍,count确实被我用坏了。(我想,不止被我一个人用坏了吧。

我们看到上面的Any干嘛的?官方解释是:

我反复阅读这个中文解释,一直无法理解。甚至早有人也提出过同样的疑问《实在看不懂MSDN关于 Any 的解释》

所以我个人理解也是“确定集合中是否有元素满足某一条件”。我们来看看any其他用法:

要求:查询教过“张三”或“李四”的老师

实现代码:

两种方式,以前我会习惯写第一种。当然我们看看生成过的sql和执行效率之后,看法改变了。

效率之差竟有近六倍

我们再对比下count:

得出奇怪的结论:

  1. 在导航属性里面使用count和使用any性能区别不大,反而FirstOrDefault() != null的方式性能最差。

  2. 在直接属性判断里面any和FirstOrDefault() != null性能区别不大,count性能要差的多。

  3. 所以,不管是直接属性还是导航属性我们都用any来判断是否存在是最稳当的

透明标识符

假如由于各种原因我们需要写下面这样逻辑的语句

我们可以写成这样更好

看生成的sql就知道了

第二种方式生成的sql要干净得多,性能也更好。

EntityFramework.Extended

这里推荐下插件EntityFramework.Extended,看了下,很不错。

最大的亮点就是可以直接批量修改、删除,不用像EF默认的需要先做查询操作。

至于官方EF为什么没有提供这样的支持就不知道了。不过使用EntityFramework.Extended需要注意以下几点:

  1. 只支持sql server

  2. 批量修改、删除时不能实现事务(也就是出了异常不能回滚)

  3. 没有联级删除

http://www.cnblogs.com/GuZhenYin/p/5482288.html

自定义IQueryable扩展方法

 最后整理下自定义的IQueryable的扩展。

 

原文地址:http://www.cnblogs.com/zhaopei/p/5721789.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

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

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

相关文章

Go语言、Docker 和新技术

转载自 Go语言、Docker 和新技术上个月,作为 Go 语言的三位创始人之一,Unix 老牌黑客罗勃派克(Rob Pike)在新文章“Go: Ten years and climbing”中,回顾了一下 Go 语言的发展过程。其中提到,Go 语言这十年…

服务器 .err文件,IIS 关闭HTTPERR(IIS日志)的方法

关闭HTTPERR的方法运行里输入 regedit 进入注册表编辑器[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters]在右边 点鼠标右键 新建dword值 EnableErrorLogging 重新启动服务器就可以了"EnableErrorLogging"dword:00000000重起后,2…

数据库的实现【笔记】

一、创建数据库1.简单的方式create database 数据库名2.指定主文件和日志文件参数create database 数据库名 on [primary](name数据库逻辑名, --数据库名_datafilename数据库主文件(包括路径),--E:\第二期\第二章数据库的实现\数据库名_d…

Entity Framework Core Lolita

这是Entity Framework Core的一个轻量的扩展,提供批量更新和删除操作的支持。而且这个库出自中国一位MVP之手,虽然内容是英文,也很简单,相信你也能看懂。 This is a light-weight extension which provides bulk update and delet…

如何显示服务器控件,Panel Web 服务器控件概述

Panel Web 服务器控件概述10/22/2014本文内容更新:2007 年 11 月Panel Web 服务器控件在 ASP.NET 网页内提供了一种容器控件,您可以将它用作静态文本和其他控件的父级。本主题包括:背景代码示例类参考背景可以将 Panel 控件用作其他控件的容器…

使用GZIP和Zip压缩Java数据流

转载自 使用GZIP和Zip压缩Java数据流本文通过对数据压缩算法的简要介绍,然后以详细的示例演示了利用java.util.zip包实现数据的压缩与解压,并扩展到在网络传输方面如何应用java.util.zip包现数据压缩与解压综述 许多信息资料都或多或少的包含一些多余的…

Asp.net Core基于MVC框架实现PostgreSQL操作

简单介绍 Asp.net Core最大的价值在于跨平台、跨平台、跨平台。重要的事情说三遍。但是目前毕竟是在开发初期,虽然推出了1.0.0 正式版,但是其实好多功能还没有完善。比方说编译时的一些文件编码问题,辅助工具Tools的一些Bug,还有一…

sql高级查询

子查询:是嵌套在select ,insert ,update ,delete语句或者其他的子查询中的查询语句。 一、一般的使用方式:select * from 表1 where 列 运算符 (子查询)注意:1.先执行子查询,在执行外查询(主查询…

小米miui系统已停止服务器,小米两款机型停止 MIUI 更新,明天发布最终体验版固件...

原标题:小米两款机型停止 MIUI 更新,明天发布最终体验版固件11 月 21 日消息, MIUI 官方预告 MIUI 于 2018 年 11 月 22 日发布小米手机 5 、红米 Note 3 全网通的最后一个 MIUI 10 体验版/开发版 8.11.22 ,两款机型将不再支持后续…

Java压缩技术(一) ZLib

转载自 Java压缩技术(一) ZLib 有关ZLib可参见官方主页 http://www.zlib.net/ ZLib可以简单的理解为压缩/解压缩算法,它与ZIP、RAR等归档算法有所不同,与bzip2比较接近。 压缩工具代码如下: Java代码 /** * 2009-9-9…

【送书活动】机器学习项目开发实战

出版时间 2016-08-01 定价:59元 作者: Mathias Brandewinder是Microsoft F# 最有价值专家(MVP),住在加州旧金山,在那里他为Clear Lines Consulting工作。作为一名当之无愧的数学极客,他很早就对…

刀剑斗神传只显示11个服务器,与官方服务器互通 《刀剑斗神传》电脑版即将上线...

乱世江湖动作MMO手游《刀剑斗神传》将于12月29日开启公测,为方便玩家更好的体验游戏,游戏将推出电脑版,并与iOS、安卓的官方服务器实现数据互通。不管是在公交地铁上用手机,还是在自己温馨的小居室用电脑,你可以选择自…

深入wepy源码:wpy文件编译过程

转载自 深入wepy源码:wpy文件编译过程wepy 是腾讯开源的一款小程序框架,主要通过预编译的手段,让开发者采用类 Vue 风格开发。 让我们一起看看, wepy 是如何实现预编译的。先放上一张官网的流程图,后面的分析可以参考该…

sql事务、视图和索引

一、事务:1.概念:是单个逻辑单元执行的一系列操作(一个事务中有多个sql语句),这个操作作为一个整体一起提交,要么执行,要么都不执行,多个事务操作是一个不可分割的逻辑单元。2.事务的…

qq空间说说服务器维护,如何解决QQ空间说说发表不了

如何解决QQ空间说说发表不了我的今天也是这种情况几个qq都发表不了,都不知道怎么办了,然后过一会儿又能发表了但是现在有发表不了了...是空间的系统问题吧!还有啊就是不要加什么敏感词汇不然也发表不了一、如果您打开是提示“服务器忙&#x…

Win10上运行Docker

1. 前言 Docker最近推出了可以运行在Win10和Mac上的稳定版本,让我们赶紧来体验一下。 Docker发布Mac和Windows 的目标非常简单——开发者可以更加简单方便地在研发机器上使用Docker。下面是此次版本所改进的地方: 更快更可靠——在本地开发环境上&#x…

sql serve存储过程

存储过程一.概念:预先编译好的sql程序,可以包含:操作数据、变量、控制语句,增删改查操作都可以,存储过程是保存在数据库中 的一个对象。二.好处:1.安全性更高2.减少了网络流量3.提高速度,性能更高4.模…

JAVA数据库连接池实现

转载自 JAVA数据库连接池实现连接池的管理用了了享元模式,这里对连接池进行简单设计。 一、设计思路1.连接池配置属性DBbean:里面存放可以配置的一些属性2.连接池接口IConnectionPool:里面定义一些基本的获取连接的一些方法3.接口实现Conne…

在.NET开发面向Oracle数据库的应用程序

其实这个不是一个什么新的话题。但是之前在多次项目中,总是遇到大家针对Oracle数据库的访问时,会有各种各样的问题,最基本的就是要在客户端安装各种client,版本不一样的话还有各种问题。 静下心来看看,其实也没有那么难…

服务器ubuntu系统版本选型原则,系统集成 - 选择Ubuntu服务器版操作系统的六大理由_服务器应用_Linux公社-Linux系统门户网站...

二. 系统集成(1)集成现有的系统Ubuntu服务器版本用常用的身份认证方式和服务入口工具简单地集成企业现有的客户/服务器结构。我们都知道系统集成技术的重要性,这也是Ubuntu团队花费大量时间研究如何实现服务器与基础设施简单融合的原因。(2)简单的验证方式验证功能对…