您不能够不精晓的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 相关联的
DataReader,必须首先将它倒闭。”

图片 7

化解方案:

  • 方案1、设定ConnectionString加上MultipleActiveResultSets=true,但只适用于SQL
    2007事后的版本
  • 方案2、大概先读出放置在List中

3.上述两点仅为热身,大家说的圈套才刚刚起头!

图片 8

然后大家点击张开迷你Profiler工具(不要被吓到)

图片 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
    二零零七未来的版本
  • 方案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

联表查询总结

要求:查询前玖18个学生考试连串(“模拟考试”、“正式考试”)、考试次数、语文平均分、学生姓名,且考试次数超过等于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

联表查询总括

务求:查询前一百个学生考试项目(“模拟考试”、“正式考试”)、考试次数、语文平均分、学生姓名,且考试次数抢先等于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。

好像好像很完善了。其实否则,大家抢先56%意况排序是动态的。比如,我们会特别前端页面差异的操作须求不相同字段的例向外排水序。这大家后台应该咋办啊?

图片 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#基础知识加强系列

迎接热心园友补充!

相关文章