你不能不清楚的EF知识和阅历www.6799.com

本性进步之AsNoTracking

www.6799.com 1

咱俩看变化的sql

www.6799.com 2

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

www.6799.com 3

笔者们看变化的sql

www.6799.com 4

sql是浮动的大同小异,不过进行时间却是4.8倍。原因仅仅只是第一条EF语句多加了二个AsNoTracking。

注意:

  • AsNoTracking干什么的啊?无追踪查询而已,也便是说查询出来的靶子不可能一直做修改。所以,我们在做多少群集查询展现,而又没有供给对聚集修改并创新到数据库的时候,一定毫无遗忘加上AsNoTracking。
  • 倘若查询进度做了select映射就无需加AsNoTracking。如:db.Students.Where(t=>t.Name.Contains(“张三”)).select(t=>new
    (t.Name,t.Age)).ToList();

推荐MiniProfiler插件

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

我们选用EF和在十分的大程度进步了支付速度,可是随着带来的是过多性质低下的写法和扭转不太高速的sql。

尽管如此大家能够使用SQL Server
Profiler来监控施行的sql,可是个人以为正是麻烦,每一次供给张开、过滤、清除、关闭。

在此间刚毅推荐贰个插件MiniProfiler。实时监督页面请求对应实行的sql语句、实践时间。轻易、方便、针对性强。

如图:(具体行使和介绍请移步)

www.6799.com 5

联表查询总括

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

代码如下:

www.6799.com 6

看到那样的代码,作者第一反响是惨了。又在循环实行sql了。监察和控制如下:

www.6799.com 7

事实上,大家只要求有些改作育把101条sql产生1条,如下:

www.6799.com 8

马上变1条。

www.6799.com 9

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

www.6799.com 10

意识那仅仅只是查询结果群集而已,个中的按考试项目来计算是程序得到全部数据后在图谋的(而不是在数据库内总计,然后径直回到结果),这样平等是浪费了数据库查询数据传输。

关于连接查询分组总括大家得以应用SelectMany,如下:

www.6799.com 11

监察sql如下:(是或不是轻便多了啊?)

www.6799.com 12

关于SelectMany资料:

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

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

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的用法)

供给:查询是不是存在名为“张三”的学员。(你的代码会如何写吗?)

www.6799.com 13

率先种?第三种?第二种?呵呵,小编原先正是运用的第一种,然后有些人讲“你count被你用坏了”,后来笔者想了想了怎么就被笔者用坏了呢?直到比较了那八个语句的性质后作者知道了。

www.6799.com 14

个性之差竟有三百多倍,count确实被小编用坏了。(小编想,不仅被笔者壹位用坏了吧。)

大家看到上边的Any干嘛的?官方表达是:

www.6799.com 15

本身屡屡阅读那个汉语演说,向来无法知晓。以至早有人也提议过同样的疑云《实质上看不懂MSDN关于
Any
的阐述

从而本人个人明白也是“鲜明集结中是不是有成分知足某一原则”。大家来看望any其余用法:

须求:查询教过“张三”或“李四”的助教

达成代码:

www.6799.com 16

两种方法,从前作者会习于旧贯写第一种。当然大家看看生成过的sql和实行功用之后,观念改变了。

www.6799.com 17

频率之差竟有近六倍

咱俩再对照下count:

www.6799.com 18

www.6799.com 19

得出奇异的定论:

  1. 在导航属性之中使用count和应用any质量分别十分的小,反而FirstOrDefault()
    != null的法子品质最差。
  2. 在直接属性判别在那之中any和FirstOrDefault() !=
    null品质分别非常小,count质量要差的多。
  3. 之所以,不管是一向属性依旧导航属性大家都用any来推断是或不是留存是最得当的。

foreach循环的陷进 

1.关于推迟加载

www.6799.com 20

请看上海教室红框。为何StudentId有值,而Studet为null?因为运用code
first,必要安装导航属性为virtual,才会加载延迟加载数据。

www.6799.com 21

2.关于在循环中做客导航属性的老大管理(接着上面,加上virtual后会报以下万分)

“已有张开的与此 Command 相关联的
DataReader,必须首先将它停业。”

www.6799.com 22

化解方案:

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

3.之上两点仅为热身,大家说的牢笼才刚刚起头!

www.6799.com 23

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

www.6799.com 24

www.6799.com 25

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

www.6799.com 26

再看MiniProfiler的督察(须臾间101条sql变成了1条,这里面包车型大巴品质由此可见。)

www.6799.com 27

【转】你必须理解的EF知识和经验

自定义IQueryable增加方法

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

 www.6799.com 28

www.6799.com 29

 

补充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#基础知识加强连串

接待热心园友补充!

属性提高之AsNonUnicode

www.6799.com 30

监察和控制到的sql

www.6799.com 31

笔者们来看EF符合规律状态变化的sql会在后边带上“N”,要是大家抬高DbFunctions.AsNonUnicode生成的sql是绝非“N”的,当你意识带上“N”的sql比未有带“N”的
sql查询速度慢多数的时候这就知道该怎么办。

(从前用oracle的时候带不带“N”查询功用差异特别令人侧目,明日用sql
server测试并不曾察觉什么样差别www.6799.com 32。还应该有小编意识EF6会依据数据库中是nvarchar的时候才会生成带“N”的sql,oracle数据库没测试,有意思味的同学能够测试下)

推荐MiniProfiler插件

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

我们接纳EF和在十分大程度升高了付出进度,可是随着推动的是累累性格低下的写法和变化不太高速的sql。

即便我们得以应用SQL Server
Profiler来监察和控制实施的sql,然则个人以为正是麻烦,每一回要求开采、过滤、清除、关闭。

在此间刚毅推荐叁个插件MiniProfiler。实时监督页面请求对应实施的sql语句、试行时间。轻易、方便、针对性强。

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

www.6799.com 33

AutoMapper工具

地点我们通过Include突显的实施表的连接查询分明是天经地义的,但还远远不足。若是大家只必要查询数据的一点字段呢,下面查询全部字段岂不是很浪费内部存款和储蓄器存款和储蓄空间和应用程序与数据库数据传输带宽。

我们能够:

www.6799.com 34

对应监督到的sql:

www.6799.com 35

咱俩见到变化的sql,查询的字段少了众多。唯有大家来得列出来字段的和叁个StudentId,StudentId用来连接查询条件的。

没有错,那样的艺术很准确。然则有未有何样越来越好的方案或艺术吧?答案是显著的。(不然,也不会在此地屁话了。)假若表字段相当的多,我们供给接纳的字段也不行多,导航属性也相当多的时候,那样的手动映射就体现不那么美观了。那么接下去大家初步介绍使用AutoMapper来完毕映射:

留神:首先需求NuGet下载AutoMapper。(然后导入命名空间 using
AutoMapper; using AutoMapper.QueryableExtensions;)

www.6799.com 36

www.6799.com 37

大家看看上面查询语句未有贰个个的手动映射,而映射都以独自安顿了。其中CreateMap应该是要写到Global.asax文件之中的。(其实相当于分手了炫丽部分,清晰了查询语句。细心的同室恐怕注意到了,这种办法还免去了当仁不让Include)

www.6799.com 38

我们看出了变化的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

lamdba条件构成

渴求:依照分化景况询问,只怕景况

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

兑当代码:

www.6799.com 39

是否味到了同等的臭味www.6799.com 40。下边我们来灵活组装Lamdba条件。

缓慢解决方案:

www.6799.com 41www.6799.com 42

这段代码作者也是从英特网偷的,具体链接找不到了。

接下来大家的代码能够写成:

www.6799.com 43

有没有美美哒一点www.6799.com 44。然后我们看看生成的sql是否科学:

www.6799.com 45

数量图谋

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

www.6799.com 46

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

AutoMapper工具

上边我们经过Include显示的推行表的连接查询分明是未可厚非的,但还非常不足。假使大家只需求查询数据的一点字段呢,上边查询全体字段岂不是很浪费内部存款和储蓄器存款和储蓄空间和应用程序与数据库数据传输带宽。

我们能够:

www.6799.com 47

对应监督到的sql:

www.6799.com 48

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

不错,那样的必定要经过的地方很科学。可是有没有怎么样越来越好的方案或方法吗?答案是必定的。(不然,也不会在这里屁话了。)借使表字段相当多,我们要求动用的字段也非凡多,导航属性也十分的多的时候,那样的手动映射就呈现不那么狼狈了。那么接下去大家初阶介绍使用AutoMapper来形成映射:

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

www.6799.com 49

www.6799.com 50

小编们来看地点查询语句未有三个个的手动映射,而映射都以独立布置了。个中CreateMap应该是要写到Global.asax文件之中的。(其实也便是分离了绚烂部分,清晰了查询语句。细心的同校也许注意到了,这种格局还免去了积极Include)

www.6799.com 51

作者们见到了变化的sql和前边有多少不一,但只生成了一条sql,并且结果也是天经地义的。(其实便是多了一条CASE WHEN ([Extent2].[Id] IS
NOT NULL) THEN 1 END AS
[C1]。看起来那条语句并从未什么样实际意义,不过那是AutoMapper生成的sql,相同的时间本身也表示不晓得为啥和EF生成的分化)

诸如此类做的实惠?

  1. 避免在循环中走访导航属性数14次实行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

自定义IQueryable扩张方法

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

 www.6799.com 52

www.6799.com 53

 

补充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#基础知识加强连串

应接热心园友补充!

数码筹划

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

www.6799.com 54

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

晶莹剔透标志符

若是由于各类缘由大家供给写上边这样逻辑的言辞

www.6799.com 55

小编们得以写成这么更加好

www.6799.com 56

看生成的sql就了然了

www.6799.com 57

第两种方法转换的sql要深透得多,质量也越来越好。

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

务求:查询名字里面包蕴“张三”的学习者,先按名字排序,再按年龄排序。

www.6799.com 58

www.6799.com 59

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

www.6799.com 60

www.6799.com 61

不错不错,便是我们想要的功力。假如你不想用ThenBy,且都以升序的话,大家也能够:

www.6799.com 62

www.6799.com 63

转换的sql是毫无二致的。与OrderBy、ThenBy对应的降序有OrderByDescending、ThenByDescending。

类似好像很完善了。其实不然,大家大多数情景排序是动态的。举例,大家会更加的前端页面不一样的操作须求差异字段的两样排序。那大家后台应该怎么做吧?

www.6799.com 64

自然,那样成功是没难点的,只要您愿意。能够这样多或然的判断有未有认为分外SB?是的,大家本来有更加好的消除方案。假若OrderBy可以直接传字符串???

赶尽杀绝方案:

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

www.6799.com 65

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

www.6799.com 66

咱俩看下生成的sql:

www.6799.com 67

和我们想要的效应完全符合,是否感觉美美哒!!

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

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();//回滚事务
    }
}

注意:以下内容固然未有极度表达,暗中同意使用的EF6.0版本,code first形式。

联表查询总计

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

代码如下:

www.6799.com 68

阅览这么的代码,笔者先是反响是惨了。又在循环实践sql了。监察和控制如下:

www.6799.com 69

实质上,我们只须求有个别更改就把101条sql形成1条,如下:

www.6799.com 70

马上变1条。

www.6799.com 71

笔者们开辟查看详细的sql语句

www.6799.com 72

发觉那仅仅只是查询结果会集而已,当中的按考试种类来统计是先后得到独具数据后在总括的(而不是在数据库内总计,然后直接回到结果),那样同样是浪费了数据库查询数据传输。

有关连接查询分组总结大家能够动用SelectMany,如下:

www.6799.com 73

监察sql如下:(是还是不是精简多了啊?)

www.6799.com 74

关于SelectMany资料:

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

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

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();//回滚事务
    }
}

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

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

www.6799.com 75

www.6799.com 76

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

www.6799.com 77

www.6799.com 78

不错不错,就是大家想要的效果。假让你不想用ThenBy,且都是升序的话,大家也得以:

www.6799.com 79

www.6799.com 80

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

就如好像很周详了。其实不然,大家半数以上动静排序是动态的。举个例子,大家会更为前端页面差异的操作要求差别字段的例向外排水序。那大家后台应该如何是好呢?

www.6799.com 81

自然,那样成功是没难点的,只要您愿意。能够这么多或许的论断有未有痛感非常SB?是的,大家当然有越来越好的消除方案。假设OrderBy能够一贯传字符串???

消除方案:

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

www.6799.com 82

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

www.6799.com 83

咱俩看下生成的sql:

www.6799.com 84

和大家想要的遵循完全符合,是或不是认为美美哒!!

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

属性提高之AsNonUnicode

www.6799.com 85

监察到的sql

www.6799.com 86

作者们看来EF正常状态变化的sql会在前头带上“N”,借使大家增加DbFunctions.AsNonUnicode生成的sql是不曾“N”的,当你发觉带上“N”的sql比尚未带“N”的
sql查询速度慢许多的时候那就理解该怎么做。

(以前用oracle的时候带不带“N”查询作用差异特别引人侧目,今日用sql
server测试并从未发掘什么样异样www.6799.com 87。还大概有本人发觉EF6会根据数据库中是nvarchar的时候才会生成带“N”的sql,oracle数据库没测试,风趣味的同学能够测试下)

foreach循环的陷进 

1.有关推迟加载

www.6799.com 88

请看上海教室红框。为何StudentId有值,而Studet为null?因为使用code
first,供给设置导航属性为virtual,才会加载延迟加载数据。

www.6799.com 89

2.有关在循环中做客导航属性的要命管理(接着下面,加上virtual后会报以下相当)

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

www.6799.com 90

减轻方案:

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

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

www.6799.com 91

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

www.6799.com 92

www.6799.com 93

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

www.6799.com 94

再看迷你Profiler的督查(弹指间101条sql形成了1条,那之中的性质总之。)

www.6799.com 95

透明标志符

一经由于各类原因我们要求写下边那样逻辑的言语

www.6799.com 96

咱俩得以写成那样更加好

www.6799.com 97

看生成的sql就精通了

www.6799.com 98

其次种方法转变的sql要干净得多,质量也更加好。

lamdba条件构成

渴求:依照差别情状询问,大概情状

  1. 查询name=“张三” 的享有学生
  2. 询问name=“张三” 或许 age=18的装有学生

兑今世码:

www.6799.com 99

是否味到了一致的恶臭www.6799.com 100。上面大家来灵活组装Lamdba条件。

消除方案:

www.6799.com 101www.6799.com 102

这段代码作者也是从英特网偷的,具体链接找不到了。

接下来我们的代码能够写成:

www.6799.com 103

有未有美美哒一点www.6799.com 104。然后我们看看生成的sql是不是正确:

www.6799.com 105

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

渴求:查询是不是留存名为“张三”的学童。(你的代码会怎么写吧?)

www.6799.com 106

第一种?第两种?第二种?呵呵,笔者原先就是应用的第一种,然后有些许人会说“你count被你用坏了”,后来自家想了想了怎么就被本人用坏了呢?直到相比了那多个语句的属性后笔者精通了。

www.6799.com 107

天性之差竟有三百多倍,count确实被小编用坏了。(小编想,不仅被笔者一人用坏了吧。)

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

www.6799.com 108

自身多次阅读那个中文表达,平昔不恐怕领悟。以至早有人也提出过同样的难点《实质上看不懂MSDN关于
Any
的表明

于是本身个人精通也是“鲜明集结中是或不是有成分满意某一原则”。大家来探视any其他用法:

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

福寿绵绵代码:

www.6799.com 109

二种方法,从前小编会习贯写第一种。当然大家看看生成过的sql和实行功能之后,观念改动了。

www.6799.com 110

频率之差竟有近六倍

咱俩再对照下count:

www.6799.com 111

www.6799.com 112

得出奇异的下结论:

  1. 在导航属性之中使用count和利用any品质分别相当小,反而FirstOrDefault()
    != null的办法质量最差。
  2. 在一直属性推断当中any和FirstOrDefault() !=
    null质量分别非常小,count品质要差的多。
  3. 从而,不管是一贯属性照旧导航属性我们都用any来推断是还是不是留存是最稳妥的。

瞩目:以下内容假诺未有特地表明,私下认可使用的EF6.0版本,code first方式。