【转】你要掌握之EF知识及更

【转】你要明白的EF知识以及更

留意:以下内容如果无专门说明,默认使用的EF6.0版本,code first模式。

推荐MiniProfiler插件

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

俺们应用EF和在老大要命程度提高了开发进度,不过随后带动的凡成百上千特性低下的写法和生成不太高速之sql。

尽管我们可以采取SQL Server
Profiler来监控执行之sql,不过个人认为就是麻烦,每次要开拓、过滤、清除、关闭。

在此间强烈推荐一个插件MiniProfiler。实时督查页面请求对诺实行的sql语句、执行时间。简单、方便、针对性强。

如图:(实际用和介绍请走)

多少准备

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

后面会受出demo代码下充斥链接

foreach循环的陷进 

1.关于推迟加载

伸手看上图红框。为什么StudentId有价,而Studet为null?因为用code
first,需要设置导航属性为virtual,才会加载延迟加载数据。

2.有关在循环中访问导航属性的良处理(接着上面,加上virtual后会报以下很)

“已生开拓的同此 Command 相关联的
DataReader,必须首先将她倒闭。”

缓解方案:

  • 方案1、设定ConnectionString加上MultipleActiveResultSets=true,但只是适用于SQL
    2005以后的版
  • 方案2、或者先念来放置于List中

3.以上两接触只有为热身,我们说之陷阱才刚刚开始!

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

解决方案:使用Include著连续查询(注意:需要手动导入using System.Data.Entity
不然Include只能传表名字符串)。

复看MiniProfiler的监督(瞬间101条sql变成了1长达,这其间的性可想而知。)

AutoMapper工具

面我们经过Include显示的执行表的连查询显然是科学的,但还不够。如果我们只待查询数据的一些字段呢,上面查询有字段岂不是老大浪费内存存储空间和应用程序与数据库数据传带富。

咱们好:

对承诺监督及之sql:

咱俩来看变化的sql,查询的字段少了众。只有咱展示列出来字段的同一个StudentId,StudentId用来连续查询条件的。

然,这样的不二法门充分是。可是有没有出什么还好之方案还是方式呢?答案是早晚之。(不然,也未会见以这里屁话了。)如果表字段非常多,我们得动用的字段也充分多,导航属性也不行多的早晚,这样的手动映射就显示不那么尴尬了。那么连下去我们开始介绍以AutoMapper来成功投:

只顾:首先需要NuGet下载AutoMapper。(然后导入命名空间 using
AutoMapper; using AutoMapper.QueryableExtensions;)

咱俩看看地方查询语句没有一个个的手动映射,而映射都是独自布置了。其中CreateMap应该是如果描写到Global.asax文件之中的。(其实呢就算是分别了照部分,清晰了询问语句。细心的同室或注意到了,这种方法尚非去矣当仁不让Include)

咱视了转变的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次。(按考试类别分类统计)

代码如下:

盼这么的代码,我第一反响是灾难性了。又当循环执行sql了。监控如下:

骨子里,我们才需要有些改变就将101长sql变成1漫长,如下:

马上变1条。

我们开拓查看详细的sql语句

发觉及时仅仅只是查询结果集合而已,其中的按考试项目来统计是先后将到拥有数据后当算的(而未是在数据库内计算,然后直接回结果),这样平等是浪费了数据库查询数据传。

关于连接查询分组统计我们可利用SelectMany,如下:

监察sql如下:(是免是精简多了呢?)

关于SelectMany资料:

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

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

性能提升的AsNonUnicode

监察及之sql

我们来看EF正常情况变化的sql会当眼前带及“N”,如果我们添加DbFunctions.AsNonUnicode生成的sql是绝非“N”的,当您意识带来齐“N”的sql比从来不拉动“N”的
sql查询速度迟滞很多底上那么就掌握该怎么处置。

(以前之所以oracle的当儿带非带“N”查询效率差别特别强烈,今天因故sql
server测试并没察觉什么区别。还有我发觉EF6会根据数据库中凡nvarchar的下才会生成带“N”的sql,oracle数据库没测试,有趣味之同校可以测试下)

特性提升的AsNoTracking

俺们看变化的sql

sql是生成的等同型一样,但是实行时可是4.8倍。原因仅仅只是第一长长的EF语句子多加了一个AsNoTracking。

注意:

  • AsNoTracking干啊的吗?无跟踪查询而已,也就是说查询出来的靶子不能够一直开修改。所以,我们于召开多少集合查询显示,而同时休需针对聚集修改并创新至数据库的时刻,一定不要忘记加上AsNoTracking。
  • 若是查询过程做了select映射就非需加AsNoTracking。如:db.Students.Where(t=>t.Name.Contains(“张三”)).select(t=>new
    (t.Name,t.Age)).ToList();

基本上字段组合排序(字符串)

渴求:查询名字里含有“张三”的生,先随名排序,再按照年排序。

哟,不对啊。按名排序为年龄排序覆盖了。我们相应为此ThenBy来做排序。

不错不错,正是我们怀念如果的效能。如果你切莫思就此ThenBy,且还是升序的言辞,我们也得:

转的sql是同一的。与OrderBy、ThenBy对应之降序有OrderByDescending、ThenByDescending。

类好像死完善了。其实不然,我们大部分状况排序是动态的。比如,我们见面越前端页面不同的操作要求不同字段的不同排序。那我们后台应该怎么开为?

当然,这样就是没问题之,只要你愿意。可以这么多或者的判断有没有发出觉异常SB?是的,我们本发更好之解决方案。要是OrderBy可以一直传字符串???

釜底抽薪方案:

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

接下来上面又增长同时可恨的代码可以形容成:

咱看下别的sql:

暨咱们纪念使的功效完全符合,是匪是深感美美哒!!

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

lamdba条件做

要求:根据不同状况询问,可能情况

  1. 询问name=“张三” 的备学员
  2. 查询name=“张三” 或者 age=18底兼具学员

心想事成代码:

凡无是味及了平的恶臭。下面我们来灵活组装Lamdba条件。

釜底抽薪方案:

当下段代码我哉是自网上偷的,具体链接找不至了。

然后我们的代码可以写成:

来没发出得意美哒一点。然后我们省生成的sql是否对:

EF的预热

http://www.cnblogs.com/dudu/p/entity-framework-warm-up.html

count(*)被公用老了为(Any的用法)

要求:查询是否有名字为“张三”的学习者。(你的代码会咋样形容为?)

率先种植?第二种?第三栽?呵呵,我以前就是是以的第一种植,然后有人说“你count被你用生了”,后来自怀念了想了怎么就为我之所以很了邪?直到对比了即三只告知词之属性后我懂了。

性能的差竟有三百基本上加倍,count确实被我用特别了。(我想,不止于我一个人数所以老了吧。)

俺们见到上面的Any干嘛的?官方说明是:

自己一再读者中文解说,一直无法理解。甚至早有人吗提出过一样的谜《实则看不懂MSDN关于
Any
的分解》

就此自己个人掌握呢是“确定集合中是否来素满足某平等法”。我们来探望any其他用法:

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

贯彻代码:

零星栽方式,以前我会习惯写第一栽。当然我们看那个成了之sql和实行效率之后,看法改变了。

频率的异竟有近六倍

咱俩还比下count:

得出奇怪的结论:

  1. 每当导航属性之中用count和下any性能分不生,反而FirstOrDefault()
    != null的方性能最好差。
  2. 在一直性判断其中any和FirstOrDefault() !=
    null性能分不要命,count性能使差的大都。
  3. 故而,不管是一直性还是导航属性我们还用any来判定是否在是最为稳妥的。

晶莹剔透标识符

如若由于各种原因我们得写下面这样逻辑的话语

咱得写成这样重复好

看生成的sql就理解了

仲栽艺术变的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();//回滚事务
    }
}

自从定义IQueryable扩展方法

 最后整理下由定义的IQueryable的扩张。

 

 

补充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#基础知识巩固系列》

欢迎热心园友补充!

相关文章