默认使用的EF6.0版本

【转】你不可能不通晓的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#基础知识巩固体系

欢迎热心园友补充!

相关文章