你必得知道的EF知识和阅历爱博体育app

【转】你必须驾驭的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,不过个人以为正是麻烦,每趟要求开发、过滤、清除、关闭。

在此地刚强推荐三个插件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 相关联的
Data里德r,必得首先将它倒闭。”

爱博体育app 7

应用方案:

  • 方案1、设定ConnectionString加上MultipleActiveResultSets=true,但只适用于SQL
    二零零六今后的版本
  • 方案2、或然先读出放置在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
    二〇〇六之后的本子
  • 方案2、或许先读出放置在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

咱俩看到地点查询语句未有叁个个的手动映射,而映射都以独自安插了。个中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

联表查询总计

须求:查询前九十八个学生考试体系(“模拟考试”、“正式考试”)、考试次数、语文平均分、学生姓名,且考试次数抢先等于3次。(按考试项目分类总括)

代码如下:

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

联表查询计算

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

代码如下:

爱博体育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. 爱博体育app,在导航属性之中使用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 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#基础知识加强类别

迎接热心园友补充!

相关文章