您不可以不明白的EF知识和经验,你必须领会的EF知识和阅历新普金娱乐

【转】你不可能不清楚的EF知识和阅历

留意:以下内容即使没有专门表明,默认使用的EF6.0版本,code first格局。

留神:以下内容如若没有专门表明,默认使用的EF6.0版本,code first情势。

推荐MiniProfiler插件

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

我们采用EF和在很大程度提升了开支速度,可是随后带动的是多多益善性能低下的写法和生成不太高速的sql。

尽管我们可以选拔SQL Server
Profiler来监控实施的sql,然则个人认为就是麻烦,每一遍需要开拓、过滤、清除、关闭。

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

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

新普金娱乐 1

推荐MiniProfiler插件

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

俺们选拔EF和在很大程度提高了开发进度,但是随后带动的是累累性质低下的写法和生成不太高速的sql。

虽然如此大家可以使用SQL Server
Profiler来监控执行的sql,不过个人觉得就是麻烦,每一遍需要开拓、过滤、清除、关闭。

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

如图:(实际使用和介绍请移步)

新普金娱乐 2

数码准备

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

新普金娱乐 3

末端会给出demo代码下载链接

数据准备

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

新普金娱乐 4

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

foreach循环的陷进 

1.有关推迟加载

新普金娱乐 5

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

新普金娱乐 6

2.关于在循环中做客导航属性的不得了处理(接着下面,加上virtual后会报以下分外)

“已有开拓的与此 Command 相关联的
Data里德(Reade)r,必须首先将它倒闭。”

新普金娱乐 7

解决方案:

  • 方案1、设定ConnectionString加上MultipleActiveResultSets=true,但只适用于SQL
    2005将来的版本
  • 方案2、或者先读出放置在List中

3.之上两点仅为热身,我们说的牢笼才刚刚开首!

新普金娱乐 8

接下来我们点击打开MiniProfiler工具(不要被吓到)

新普金娱乐 9

新普金娱乐 10

釜底抽薪方案:使用Include展示连续查询(注意:需要手动导入using System.Data.Entity
不然Include只可以传表名字符串)。

新普金娱乐 11

再看MiniProfiler的监察(刹那间101条sql变成了1条,这里面的属性可想而知。)

新普金娱乐 12

foreach循环的陷进 

1.关于推迟加载

新普金娱乐 13

新普金娱乐,请看上图红框。为啥StudentId有值,而Studet为null?因为运用code
first,需要安装导航属性为virtual,才会加载延迟加载数据。

新普金娱乐 14

2.有关在循环中走访导航属性的百般处理(接着下边,加上virtual后会报以下非常)

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

新普金娱乐 15

缓解方案:

  • 方案1、设定ConnectionString加上MultipleActiveResultSets=true,但只适用于SQL
    2005后头的本子
  • 方案2、或者先读出放置在List中

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

新普金娱乐 16

下一场我们点击打开MiniProfiler工具(不要被吓到)

新普金娱乐 17

新普金娱乐 18

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

新普金娱乐 19

再看MiniProfiler的监督(须臾间101条sql变成了1条,这中间的特性显而易见。)

新普金娱乐 20

AutoMapper工具

地点大家由此Include呈现的执行表的连日查询明显是不利的,但还不够。如若我们只需要查询数据的一些字段呢,下面查询所有字段岂不是很浪费内存存储空间和应用程序与数据库数据传输带宽。

俺们可以:

新普金娱乐 21

对应监督到的sql:

新普金娱乐 22

俺们看来变化的sql,查询的字段少了累累。唯有大家来得列出来字段的和一个StudentId,StudentId用来连续查询条件的。

不错,那样的方法很正确。不过有没有什么更好的方案或措施呢?答案是毫无疑问的。(不然,也不会在此处屁话了。)如果表字段非常多,我们需要使用的字段也非凡多,导航属性也丰硕多的时候,这样的手动映射就显得不那么雅观了。那么接下去我们起始介绍使用AutoMapper来完成映射:

在意:首先需要NuGet下载AutoMapper。(然后导入命名空间 using
AutoMapper; using AutoMapper.QueryableExtensions;)

新普金娱乐 23

新普金娱乐 24

我们见到地点查询语句没有一个个的手动映射,而映射都是独立布置了。其中CreateMap应该是要写到Global.asax文件之中的。(其实也就是分别了炫耀部分,清晰了查询语句。细心的同桌可能注意到了,这种格局还免去了积极向上Include)

新普金娱乐 25

俺们看来了变动的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

AutoMapper工具

地方我们因而Include呈现的执行表的连天查询显著是没错的,但还不够。假使我们只需要查询数据的一些字段呢,上边查询所有字段岂不是很浪费内存存储空间和应用程序与数据库数据传输带宽。

俺们可以:

新普金娱乐 26

对应监督到的sql:

新普金娱乐 27

俺们见到变化的sql,查询的字段少了成千上万。只有我们来得列出来字段的和一个StudentId,StudentId用来连续查询条件的。

科学,这样的法子很不利。不过有没有咋样更好的方案或措施呢?答案是必定的。(不然,也不会在此地屁话了。)假如表字段十分多,大家需要采纳的字段也非常多,导航属性也异常多的时候,这样的手动映射就显得不那么雅观了。那么接下去我们起头介绍使用AutoMapper来完成映射:

专注:首先需要NuGet下载AutoMapper。(然后导入命名空间 using
AutoMapper; using AutoMapper.QueryableExtensions;)

新普金娱乐 28

新普金娱乐 29

我们看出上边查询语句没有一个个的手动映射,而映射都是独立布置了。其中CreateMap应该是要写到Global.asax文件之中的。(其实也就是分手了炫耀部分,清晰了查询语句。细心的同班可能注意到了,那种办法还免去了当仁不让Include)

新普金娱乐 30

我们看看了转移的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次。(按考试体系分类总计)

代码如下:

新普金娱乐 31

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

新普金娱乐 32

骨子里,我们只需要有些改变就把101条sql变成1条,如下:

新普金娱乐 33

马上变1条。

新普金娱乐 34

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

新普金娱乐 35

察觉这仅仅只是查询结果集合而已,其中的按考试项目来总结是程序得到持有数据后在测算的(而不是在数据库内总计,然后间接重返结果),这样同样是荒废了数据库查询数据传输。

关于连接查询分组总结我们可以运用SelectMany,如下:

新普金娱乐 36

监理sql如下:(是不是简单多了啊?)

新普金娱乐 37

关于SelectMany资料:

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

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

联表查询统计

务求:查询前100个学生考试种类(“模拟考试”、“正式考试”)、考试次数、语文平均分、学生姓名,且考试次数超越等于3次。(按考试项目分类总结)

代码如下:

新普金娱乐 38

观望这般的代码,我先是感应是惨了。又在循环执行sql了。监控如下:

新普金娱乐 39

骨子里,我们只需要多少改变就把101条sql变成1条,如下:

新普金娱乐 40

马上变1条。

新普金娱乐 41

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

新普金娱乐 42

发觉那仅仅只是查询结果集合而已,其中的按考试系列来总结是先后得到所有数据后在测算的(而不是在数据库内统计,然后径直回到结果),这样平等是浪费了数据库查询数据传输。

有关连接查询分组总括我们可以动用SelectMany,如下:

新普金娱乐 43

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

新普金娱乐 44

关于SelectMany资料:

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

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

特性提高之AsNonUnicode

新普金娱乐 45

督察到的sql

新普金娱乐 46

咱俩看看EF正常状态变化的sql会在面前带上“N”,如若大家抬高DbFunctions.AsNonUnicode生成的sql是未曾“N”的,当您发现带上“N”的sql比一贯不带“N”的
sql查询速度慢很多的时候这就知道该咋办。

(以前用oracle的时候带不带“N”查询效用差异特别引人注目,前些天用sql
server测试并从未察觉什么样差异新普金娱乐 47。还有我意识EF6会依照数据库中是nvarchar的时候才会生成带“N”的sql,oracle数据库没测试,有趣味的同校可以测试下)

特性提高之AsNonUnicode

新普金娱乐 48

督察到的sql

新普金娱乐 49

咱俩来看EF正常状态变化的sql会在眼前带上“N”,假诺我们添加DbFunctions.AsNonUnicode生成的sql是尚未“N”的,当你发现带上“N”的sql比尚未带“N”的
sql查询速度慢很多的时候这就了解该如何是好。

(从前用oracle的时候带不带“N”查询效用差异特别扎眼,今天用sql
server测试并不曾发觉什么样区别新普金娱乐 50。还有本人发现EF6会按照数据库中是nvarchar的时候才会生成带“N”的sql,oracle数据库没测试,有趣味的同桌可以测试下)

性能提高之AsNoTracking

新普金娱乐 51

大家看变化的sql

新普金娱乐 52

sql是浮动的一模一样,然而进行时间却是4.8倍。原因仅仅只是第一条EF语句多加了一个AsNoTracking。

注意:

  • AsNoTracking干什么的呢?无跟踪查询而已,也就是说查询出来的目的不可能直接做修改。所以,我们在做多少集合查询显示,而又不需要对聚集修改并更新到数据库的时候,一定毫无忘记加上AsNoTracking。
  • 如果查询过程做了select映射就不需要加AsNoTracking。如:db.Students.Where(t=>t.Name.Contains(“张三”)).select(t=>new
    (t.Name,t.Age)).ToList();

特性提高之AsNoTracking

新普金娱乐 53

俺们看变化的sql

新普金娱乐 54

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

注意:

  • AsNoTracking干什么的吗?无跟踪查询而已,也就是说查询出来的目标不能够直接做修改。所以,我们在做多少集合查询呈现,而又不需要对聚集修改并更新到数据库的时候,一定不要遗忘加上AsNoTracking。
  • 一旦查询过程做了select映射就不需要加AsNoTracking。如:db.Students.Where(t=>t.Name.Contains(“张三”)).select(t=>new
    (t.Name,t.Age)).ToList();

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

渴求:查询名字里面富含“张三”的学童,先按名字排序,再按年龄排序。

新普金娱乐 55

新普金娱乐 56

哟,不对啊。按名字排序被年龄排序覆盖了。我们应当用ThenBy来整合排序。

新普金娱乐 57

新普金娱乐 58

不错不错,正是大家想要的意义。假设你不想用ThenBy,且都是升序的话,我们也足以:

新普金娱乐 59

新普金娱乐 60

转变的sql是同一的。与OrderBy、ThenBy对应的降序有OrderByDescending、ThenByDescending。

看似好像很全面了。其实不然,我们大部分情景排序是动态的。比如,大家会越来越前端页面不同的操作要求不同字段的两样排序。这大家后台应该咋办吧?

新普金娱乐 61

自然,这样形成是没问题的,只要你愿意。可以这样多或者的判断有没有觉得相当SB?是的,我们自然有更好的缓解方案。假设OrderBy可以从来传字符串???

缓解方案:

  1. guget下载System.Linq.Dynamic 
  2. 导入System.Linq.Dynamic命名空间
  3. 编制OrderBy的恢弘方法

新普金娱乐 62

然后下边又长又臭的代码可以写成:

新普金娱乐 63

大家看下生成的sql:

新普金娱乐 64

和大家想要的效应完全符合,是不是感到美美哒!!

【注意】:流传的排序字段前面要加排序关键字
asc或desc

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

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

新普金娱乐 65

新普金娱乐 66

哎呀,不对啊。按名字排序被年龄排序覆盖了。大家理应用ThenBy来组合排序。

新普金娱乐 67

新普金娱乐 68

不错不错,正是大家想要的效应。要是您不想用ThenBy,且都是升序的话,我们也足以:

新普金娱乐 69

新普金娱乐 70

扭转的sql是如出一辙的。与OrderBy、ThenBy对应的降序有OrderByDescending、ThenByDescending。

类似好像很完善了。其实不然,大家大部分状态排序是动态的。比如,我们会越来越前端页面不同的操作要求不同字段的两样排序。那大家后台应该怎么办啊?

新普金娱乐 71

本来,那样成功是没问题的,只要您愿意。可以如此多或者的判断有没有感觉分外SB?是的,大家自然有更好的化解方案。即便OrderBy可以直接传字符串???

解决方案:

  1. guget下载System.Linq.Dynamic 
  2. 导入System.Linq.Dynamic命名空间
  3. 编制OrderBy的扩充方法

新普金娱乐 72

然后下边又长又臭的代码可以写成:

新普金娱乐 73

俺们看下生成的sql:

新普金娱乐 74

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

【注意】:传扬的排序字段后边要加排序关键字
asc或desc

lamdba条件构成

要求:依据不同景观询问,可能意况

  1. 询问name=“张三” 的有着学生
  2. 询问name=“张三” 或者 age=18的拥有学生

贯彻代码:

新普金娱乐 75

是不是味到了千篇一律的臭气新普金娱乐 76。下边大家来灵活组装Lamdba条件。

釜底抽薪方案:

新普金娱乐 77新普金娱乐 78

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

下一场大家的代码可以写成:

新普金娱乐 79

有没有美美哒一点新普金娱乐 80。然后大家看看生成的sql是否科学:

新普金娱乐 81

lamdba条件构成

渴求:按照不同情状询问,可能情状

  1. 查询name=“张三” 的持有学员
  2. 查询name=“张三” 或者 age=18的有着学员

落实代码:

新普金娱乐 82

是不是味到了相同的臭气新普金娱乐 83。下边我们来灵活组装Lamdba条件。

缓解方案:

新普金娱乐 84新普金娱乐 85

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

然后大家的代码能够写成:

新普金娱乐 86

有没有美美哒一点新普金娱乐 87。然后我们看看生成的sql是否正确:

新普金娱乐 88

EF的预热

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

EF的预热

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

count(*)被您用坏了吧(Any的用法)

渴求:查询是否存在名字为“张三”的学员。(你的代码会怎样写吗?)

新普金娱乐 89

率先种?第两种?第两种?呵呵,我在此从前就是应用的第一种,然后有人说“你count被您用坏了”,后来自己想了想了怎么就被我用坏了呢?直到比较了那六个语句的习性后自己清楚了。

新普金娱乐 90

属性之差竟有三百多倍,count确实被我用坏了。(我想,不止被自己一个人用坏了吗。)

俺们看来下边的Any干嘛的?官方表达是:

新普金娱乐 91

自身再三阅读那一个中文表明,一贯无法知道。甚至早有人也指出过千篇一律的疑难《实际上看不懂MSDN关于
Any
的演讲

由此我个人通晓也是“确定集合中是否有元素满足某一规格”。我们来看望any其他用法:

务求:查询教过“张三”或“李四”的将官

心想事成代码:

新普金娱乐 92

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

新普金娱乐 93

频率之差竟有近六倍

咱们再对照下count:

新普金娱乐 94

新普金娱乐 95

得出奇怪的结论:

  1. 在导航属性之中使用count和使用any性能分别不大,反而FirstOrDefault()
    != null的模式性能最差。
  2. 在直接属性判断其中any和FirstOrDefault() !=
    null性能分别不大,count性能要差的多。
  3. 从而,不管是平昔属性仍旧导航属性我们都用any来判定是否存在是最稳妥的。

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

务求:查询是否存在名字为“张三”的学习者。(你的代码会怎么样写吧?)

新普金娱乐 96

先是种?第三种?第两种?呵呵,我以前就是运用的首先种,然后有人说“你count被你用坏了”,后来本人想了想了怎么就被我用坏了啊?直到比较了这四个语句的性能后自己精晓了。

新普金娱乐 97

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

我们看出下面的Any干嘛的?官方表达是:

新普金娱乐 98

自我反复阅读这多少个中文解说,一直无法了然。甚至早有人也提议过同样的疑云《骨子里看不懂MSDN关于
Any
的诠释

从而我个人了解也是“确定集合中是否有元素满意某一尺码”。我们来看看any其他用法:

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

贯彻代码:

新普金娱乐 99

二种办法,此前我会习惯写第一种。当然大家看看生成过的sql和实施功效之后,看法改变了。

新普金娱乐 100

频率之差竟有近六倍

俺们再对照下count:

新普金娱乐 101

新普金娱乐 102

得出奇怪的定论:

  1. 在导航属性之中使用count和利用any性能分别不大,反而FirstOrDefault()
    != null的办法性能最差。
  2. 在从来属性判断其中any和FirstOrDefault() !=
    null性能分别不大,count性能要差的多。
  3. 之所以,不管是直接属性依然导航属性我们都用any来判定是否留存是最稳妥的。

晶莹剔透标识符

一旦由于各类缘由我们需要写上边这样逻辑的口舌

新普金娱乐 103

大家得以写成这么更好

新普金娱乐 104

看生成的sql就知道了

新普金娱乐 105

其次种办法生成的sql要根本得多,性能也更好。

晶莹剔透标识符

假如由于各个缘由大家需要写下边这样逻辑的说话

新普金娱乐 106

咱俩得以写成这么更好

新普金娱乐 107

看生成的sql就清楚了

新普金娱乐 108

其次种情势转变的sql要彻底得多,性能也更好。

EntityFramework.Extended

此处推荐下插件EntityFramework.Extended,看了下,很科学。

最大的亮点就是足以一贯批量改动、删除,不用像EF默认的急需先做询问操作。

关于官方EF为何一向不提供这么的支撑就不知晓了。不过使用EntityFramework.Extended需要小心以下几点:

  1. 只支持sql server
  2. 批量修改、删除时不可能兑现业务(也就是出了这些无法回滚)
  3. 未曾联级删除
  4. 不能同EF一起SaveChanges
    详见

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

在此纠正个问题EntityFramework.Extended并不是说不可以回滚,感谢@GuZhenYin园友的指正(原谅自己事先并未动手测试)。

专注:需要NuGet下载EntityFramework.Extended,
并导入命名空间: using
EntityFramework.Extensions ;

测试代码如下:(固然注释掉手抛极度代码是可以直接更新到数据库的)

using (var ctxTransaction = db.Database.BeginTransaction())
{
    try
    {
        db.Teachers.Where(t => true).Update(t => new Teacher { Age = "1" });

        throw new Exception("手动抛出异常");

        ctxTransaction.Commit();//提交事务
    }
    catch (Exception)
    {
        ctxTransaction.Rollback();//回滚事务
    }
}

EntityFramework.Extended

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

最大的助益就是可以直接批量修改、删除,不用像EF默认的急需先做询问操作。

有关官方EF为何没有提供这样的支撑就不领会了。然则使用EntityFramework.Extended需要小心以下几点:

  1. 只支持sql server
  2. 批量修改、删除时不可能兑现业务(也就是出了非凡不能够回滚)
  3. 并未联级删除
  4. 不能同EF一起SaveChanges
    详见

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

在此纠正个问题EntityFramework.Extended并不是说不可以回滚,感谢@GuZhenYin园友的指正(原谅自己事先未曾入手测试)。

在意:需要NuGet下载EntityFramework.Extended,
并导入命名空间: using
EntityFramework.Extensions ;

测试代码如下:(假设注释掉手抛非凡代码是可以直接更新到数据库的)

using (var ctxTransaction = db.Database.BeginTransaction())
{
    try
    {
        db.Teachers.Where(t => true).Update(t => new Teacher { Age = "1" });

        throw new Exception("手动抛出异常");

        ctxTransaction.Commit();//提交事务
    }
    catch (Exception)
    {
        ctxTransaction.Rollback();//回滚事务
    }
}

自定义IQueryable扩大方法

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

 新普金娱乐 109

新普金娱乐 110

 

补充1:

First和Single的区别:前者是TOP(1)后者是TOP(2),后者如果查询到了2条数据则抛出异常。所以在必要的时候使用Single也不会比First慢多少。

补充2: 

已打包nuget提供第一手设置 Install-Package
Talk.Linq.Extensions 或nuget搜索 Talk.Linq.Extensions 

https://github.com/zhaopeiym/Talk/wiki/Talk.Linq.Extensions_demo

 

结束:

源码下载:http://pan.baidu.com/s/1o8MYozw

本文以一头至《C#基础知识巩固连串

欢迎热心园友补充!

自定义IQueryable扩大方法

 最终整理下自定义的IQueryable的扩大。

 新普金娱乐 111

新普金娱乐 112

 

补充1:

First和Single的区别:前者是TOP(1)后者是TOP(2),后者如果查询到了2条数据则抛出异常。所以在必要的时候使用Single也不会比First慢多少。

补充2: 

已打包nuget提供直接设置 Install-Package
Talk.Linq.Extensions 或nuget搜索 Talk.Linq.Extensions 

https://github.com/zhaopeiym/Talk/wiki/Talk.Linq.Extensions_demo

 

结束:

源码下载:http://pan.baidu.com/s/1o8MYozw

正文以联合至《C#基础知识巩固连串

迎接热心园友补充!

相关文章