您不能够不知道的EF知识和阅历

【转】你无法不理解的EF知识和阅历

瞩目:以下内容假使没有专门表达,暗中认可使用的EF6.0版本,code first情势。

在意:以下内容借使没有尤其表明,暗许使用的EF6.0版本,code first格局。

推荐MiniProfiler插件

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

大家应用EF和在十分的大程度升高了付出进程,可是随着带来的是累累性质低下的写法和转移不太高速的sql。

虽说大家得以应用SQL Server
Profiler来监察和控制执行的sql,但是个人认为正是麻烦,每一次需求打开、过滤、清除、关闭。

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

如图:(切实接纳和介绍请移步)

爱博体育app 1

推荐MiniProfiler插件

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

咱俩采取EF和在一点都不小程度进步了开支速度,但是随后拉动的是触目皆是性格低下的写法和生成不太高速的sql。

固然如此大家得以选择SQL Server
Profiler来监察和控制执行的sql,但是个人认为正是麻烦,每一次要求开拓、过滤、清除、关闭。

在此间强烈推荐2个插件MiniProfiler。实时监察和控制页面请求对应进行的sql语句、执行时间。简单、方便、针对性强。

如图:(切切实举行使和介绍请移步)

爱博体育app 2

多少准备

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

爱博体育app 3

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

数据准备

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

爱博体育app 4

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

foreach循环的陷进 

1.关于推迟加载

爱博体育app 5

请看上海体育地方红框。为何StudentId有值,而Studet为null?因为使用code
first,需求设置导航属性为virtual,才会加载延迟加载数据。

爱博体育app 6

2.有关在循环中做客导航属性的特别处理(接着上面,加上virtual后会报以下格外)

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

爱博体育app 7

消除方案:

  • 方案壹 、设定ConnectionString加上MultipleActiveResultSets=true,但只适用于SQL
    二零零六从此的版本
  • 方案二 、只怕先读出放置在List中

3.以上两点仅为热身,大家说的牢笼才刚刚发轫!

爱博体育app 8

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

爱博体育app 9

爱博体育app 10

消除方案:使用Include显示延续查询(注意:须求手动导入using System.Data.Entity
不然Include只好传表名字符串)。

爱博体育app 11

再看MiniProfiler的监察(须臾间101条sql变成了1条,那当中的特性综上可得。)

爱博体育app 12

foreach循环的陷进 

1.有关延迟加载

爱博体育app 13

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

爱博体育app 14

2.有关在循环中访问导航属性的分外处理(接着上边,加上virtual后会报以下非凡)

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

爱博体育app 15

涸泽而渔方案:

  • 方案1、设定ConnectionString加上MultipleActiveResultSets=true,但只适用于SQL
    二零零五从此的版本
  • 方案② 、或许先读出放置在List中

3.以上两点仅为热身,我们说的牢笼才刚刚初叶!

爱博体育app 16

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

爱博体育app 17

爱博体育app 18

消除方案:使用Include来得一而再查询(注意:要求手动导入using System.Data.Entity
不然Include只好传表名字符串)。

爱博体育app 19

再看MiniProfiler的监察(须臾间101条sql变成了1条,那之中的属性综上说述。)

爱博体育app 20

AutoMapper工具

地方我们经过Include展现的执行表的接二连三查询分明是科学的,但还不够。假诺大家只须要查询数据的少数字段呢,上面查询全体字段岂不是很浪费内部存款和储蓄器存款和储蓄空间和应用程序与数据库数据传输带宽。

作者们可以:

爱博体育app 21

对应监督到的sql:

爱博体育app 22

咱俩看来变化的sql,查询的字段少了好多。唯有大家体现列出来字段的和贰个StudentId,StudentId用来连接查询条件的。

不错,那样的措施很科学。不过有没有何更好的方案或方法吗?答案是自然的。(否则,也不会在此处屁话了。)尽管表字段卓殊多,大家供给使用的字段也越来越多,导航属性也优秀多的时候,那样的手动映射就展现不那么难堪了。那么接下去大家初叶介绍使用AutoMapper来成功映射:

小心:首先须求NuGet下载AutoMapper。(然后导入命名空间 using
AutoMapper; using AutoMapper.QueryableExtensions;)

爱博体育app 23

爱博体育app 24

作者们看看地方查询语句没有二个个的手动映射,而映射都以独自铺排了。在那之中CreateMap应该是要写到Global.asax文件之中的。(其实也正是分开了炫耀部分,清晰了询问语句。细心的同班恐怕注意到了,那种措施还免去了积极性Include)

爱博体育app 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展现的执行表的连日查询鲜明是没错的,但还不够。假设大家只须求查询数据的有个别字段呢,上边查询全部字段岂不是很浪费内部存款和储蓄器存储空间和应用程序与数据库数据传输带宽。

我们得以:

爱博体育app 26

对应监督到的sql:

爱博体育app 27

作者们见到变化的sql,查询的字段少了诸多。只有大家体现列出来字段的和二个StudentId,StudentId用来连接查询条件的。

科学,那样的主意很不利。可是有没有怎么着更好的方案或方法吗?答案是迟早的。(不然,也不会在此间屁话了。)如若表字段相当多,我们必要利用的字段也不行多,导航属性也卓殊多的时候,那样的手动映射就显得不那么赏心悦目了。那么接下去我们开端介绍使用AutoMapper来成功映射:

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

爱博体育app 28

爱博体育app 29

小编们看出上边查询语句没有1个个的手动映射,而映射都以独自安排了。个中CreateMap应该是要写到Global.asax文件之中的。(其实也便是分开了炫耀部分,清晰了询问语句。细心的同室大概注意到了,那种方法还免去了积极Include)

爱博体育app 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

联表查询计算

务求:查询前九1三个学生考试项目(“模拟考试”、“正式考试”)、考试次数、语文平均分、学生姓名,且考试次数超过等于贰次。(按考试项目分类计算)

代码如下:

爱博体育app 31

探望那般的代码,小编第壹影响是惨了。又在循环执行sql了。监察和控制如下:

爱博体育app 32

实则,大家只须求某些改变就把101条sql变成1条,如下:

爱博体育app 33

马上变1条。

爱博体育app 34

小编们开拓查看详细的sql语句

爱博体育app 35

意识那仅仅只是查询结果集合而已,个中的按考试连串来总结是程序得到独具数据后在测算的(而不是在数据库内计算,然后直接重临结果),那样平等是荒废了数据库查询数据传输。

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

爱博体育app 36

监督sql如下:(是还是不是不难多了吗?)

爱博体育app 37

关于SelectMany资料:

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

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

联表查询总计

渴求:查询前九二十一个学生考试项目(“模拟考试”、“正式考试”)、考试次数、语文平均分、学生姓名,且考试次数超越等于二次。(按考试项目分类计算)

代码如下:

爱博体育app 38

看样子那样的代码,作者首先反馈是惨了。又在循环执行sql了。监察和控制如下:

爱博体育app 39

其实,大家只必要多少改变就把101条sql变成1条,如下:

爱博体育app 40

马上变1条。

爱博体育app 41

大家打开查看详细的sql语句

爱博体育app 42

发觉那仅仅只是查询结果集合而已,当中的按考试项目来总括是先后获得拥有数据后在总括的(而不是在数据库内总括,然后径直回到结果),那样同样是浪费了数据库查询数据传输。

至于连接查询分组总括大家得以行使SelectMany,如下:

爱博体育app 43

监察sql如下:(是还是不是不难多了呢?)

爱博体育app 44

关于SelectMany资料:

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

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

天性升高之AsNonUnicode

爱博体育app 45

监察和控制到的sql

爱博体育app 46

小编们看来EF符合规律状态变化的sql会在前面带上“N”,假诺大家添加DbFunctions.AsNonUnicode生成的sql是不曾“N”的,当您发觉带上“N”的sql比尚未带“N”的
sql查询速度慢很多的时候那就清楚该怎么办。

(此前用oracle的时候带不带“N”查询功效差异尤其醒目,明天用sql
server测试并没有察觉怎么差异爱博体育app 47。还有笔者意识EF6会依据数据库中是nvarchar的时候才会生成带“N”的sql,oracle数据库没测试,有趣味的同桌可以测试下)

质量进步之AsNonUnicode

爱博体育app 48

监督检查到的sql

爱博体育app 49

大家看看EF寻常情形变化的sql会在前面带上“N”,假诺我们添加DbFunctions.AsNonUnicode生成的sql是没有“N”的,当你意识带上“N”的sql比没有带“N”的
sql查询速度慢很多的时候那就知道该如何做。

(以前用oracle的时候带不带“N”查询作用差异尤其鲜明,明日用sql
server测试并没有发现什么异样爱博体育app 50。还有本人发觉EF6会依据数据库中是nvarchar的时候才会生成带“N”的sql,oracle数据库没测试,有趣味的同窗能够测试下)

脾气升高之AsNoTracking

爱博体育app 51

咱们看变化的sql

爱博体育app 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

爱博体育app 53

我们看变化的sql

爱博体育app 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();

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

供给:查询名字里面包括“张三”的上学的小孩子,先按名字排序,再按年龄排序。

爱博体育app 55

爱博体育app 56

嗬,不对啊。按名字排序被年龄排序覆盖了。大家应该用ThenBy来组成排序。

爱博体育app 57

爱博体育app 58

不错不错,正是大家想要的职能。假设你不想用ThenBy,且都以升序的话,大家也得以:

爱博体育app 59

爱博体育app 60

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

接近好像很周详了。其实不然,大家大部分情状排序是动态的。比如,大家会特别前端页面分歧的操作需要不相同字段的不等排序。那大家后台应该如何是好吧?

爱博体育app 61

自然,那样形成是没难点的,只要你愿意。能够那样多或然的判定有没有觉得分外SB?是的,大家本来有更好的缓解方案。即使OrderBy能够向来传字符串???

不留余地方案:

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

爱博体育app 62

下一场下边又长又臭的代码能够写成:

爱博体育app 63

笔者们看下生成的sql:

爱博体育app 64

和我们想要的功用完全符合,是否深感美美哒!!

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

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

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

爱博体育app 65

爱博体育app 66

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

爱博体育app 67

爱博体育app 68

不错不错,正是大家想要的法力。假如您不想用ThenBy,且都是升序的话,我们也得以:

爱博体育app 69

爱博体育app 70

浮动的sql是平等的。与OrderBy、ThenBy对应的降序有OrderByDescending、ThenByDescending。

就如好像很周密了。其实不然,大家大多数场馆排序是动态的。比如,我们会进一步前端页面不一样的操作必要分化字段的不等排序。那我们后台应该怎么办吗?

爱博体育app 71

理所当然,那样成功是没难点的,只要你愿意。能够如此多只怕的论断有没有感觉极度SB?是的,大家自然有更好的消除方案。借使OrderBy可以直接传字符串???

缓解方案:

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

爱博体育app 72

然后上边又长又臭的代码能够写成:

爱博体育app 73

大家看下生成的sql:

爱博体育app 74

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

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

lamdba条件构成

务求:依据不一致境况询问,恐怕情形

  1. 查询name=“张三” 的有着学员
  2. 查询name=“张三” 恐怕 age=18的全体学生

落到实处代码:

爱博体育app 75

是否味到了相同的臭味爱博体育app 76。下边大家来灵活组装Lamdba条件。

缓解方案:

爱博体育app 77爱博体育app 78

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

然后我们的代码能够写成:

爱博体育app 79

有没有美美哒一点爱博体育app 80。然后大家看看生成的sql是还是不是科学:

爱博体育app 81

lamdba条件构成

必要:遵照区别景观询问,或然景况

  1. 查询name=“张三” 的具备学生
  2. 查询name=“张三” 只怕 age=18的有着学员

金镶玉裹福禄双全代码:

爱博体育app 82

是或不是味到了同样的恶臭爱博体育app 83。上边我们来灵活组装Lamdba条件。

消除方案:

爱博体育app 84爱博体育app 85

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

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

爱博体育app 86

有没有美美哒一点爱博体育app 87。然后大家看看生成的sql是或不是科学:

爱博体育app 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的用法)

渴求:查询是不是存在名字为“张三”的学习者。(你的代码会怎么着写吗?)

爱博体育app 89

率先种?第三种?第二种?呵呵,作者从前便是使用的首先种,然后有人说“你count被您用坏了”,后来本人想了想了怎么就被自个儿用坏了呢?直到相比较了那八个语句的品质后自个儿清楚了。

爱博体育app 90

属性之差竟有三百多倍,count确实被自个儿用坏了。(小编想,不止被作者一人用坏了啊。)

我们看看地点的Any干嘛的?官方表达是:

爱博体育app 91

小编数次阅读那么些中文表明,一贯不能够清楚。甚至早有人也提出过千篇一律的疑难《骨子里看不懂MSDN关于
Any
的诠释

从而本人个人知道也是“鲜明集合中是还是不是有成分满意某一尺码”。我们来看看any其余用法:

务求:查询教过“张三”或“李四”的民办教授

落到实处代码:

爱博体育app 92

两种办法,在此以前作者会习惯写第③种。当然我们看看生成过的sql和施行效能之后,看法改变了。

爱博体育app 93

频率之差竟有近六倍

大家再对照下count:

爱博体育app 94

爱博体育app 95

得出奇怪的定论:

  1. 在导航属性之中使用count和利用any品质分别非常的小,反而FirstOrDefault()
    != null的方法品质最差。
  2. 在间接属性判断在那之中any和FirstOrDefault() !=
    null质量分别十分小,count质量要差的多。
  3. 由此,不管是直接属性依旧导航属性大家都用any来判断是或不是存在是最稳当的。

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

供给:查询是不是留存名字为“张三”的学生。(你的代码会怎么着写吗?)

爱博体育app 96

第③种?第两种?第三种?呵呵,笔者原先正是使用的首先种,然后有人说“你count被你用坏了”,后来作者想了想了怎么就被自个儿用坏了吧?直到相比较了那八个语句的品质后本人精晓了。

爱博体育app 97

品质之差竟有三百多倍,count确实被小编用坏了。(笔者想,不止被自个儿一位用坏了呢。)

咱俩来看上边的Any干嘛的?官方解释是:

爱博体育app 98

自身一再阅读这么些普通话表达,一直不或然知道。甚至早有人也建议过千篇一律的疑难《其实看不懂MSDN关于
Any
的解释

由此自身个人领悟也是“明显集合中是或不是有成分满意某一规则”。大家来探视any别的用法:

务求:查询教过“张三”或“李四”的教师职员和工人

爱博体育app,贯彻代码:

爱博体育app 99

三种方法,从前小编会习惯写第二种。当然大家看看生成过的sql和实施功能之后,看法改变了。

爱博体育app 100

频率之差竟有近六倍

咱俩再对照下count:

爱博体育app 101

爱博体育app 102

得出奇怪的结论:

  1. 在导航属性之中使用count和行使any品质分别非常小,反而FirstOrDefault()
    != null的措施品质最差。
  2. 在直接属性判断个中any和FirstOrDefault() !=
    null性能分别一点都不大,count品质要差的多。
  3. 从而,不管是一贯属性依然导航属性大家都用any来判断是不是留存是最安妥的。

晶莹剔透标识符

尽管由于各个缘由我们须要写下边那样逻辑的言语

爱博体育app 103

小编们能够写成这么更好

爱博体育app 104

看生成的sql就清楚了

爱博体育app 105

其次种格局变通的sql要干净得多,质量也更好。

晶莹剔透标识符

假定由于各样缘由我们供给写下边那样逻辑的言语

爱博体育app 106

我们能够写成这么更好

爱博体育app 107

看生成的sql就知道了

爱博体育app 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的扩张。

 爱博体育app 109

爱博体育app 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的壮大。

 爱博体育app 111

爱博体育app 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#基础知识巩固种类

迎接热心园友补充!

相关文章