这段时间在项目中运用Entity Framework作为底层数据交互框架。一个字,爽。不仅提高了开发效率,省了很多代码,而且数据库也规范了很多。按照网上的一些教程初步学习,然后实际运用了,再结合MVC ,开发一个模块的增删改查,那真是一个爽歪歪。但是,随着项目不断完善,数据表越来越多,关联性也越来越复杂,问题也逐渐露出水面。首先最大的问题是数据查询慢。有个影响点是Linq里的Count(),查阅了网上许多资料,都没有好的解决方法。这个问题暂时不说,如果那位大师有良策,还不忘赐教。

影响查询慢主要问题在于数据查询,说白了不了解EF是如何执行sql查询的,什么时候进行sql查询?以什么方式进行sql查询的?

我做了一个demo,以微软的Northwind作为数据库,有个Customers表和Orders表,Orders表里有个字段CustomerID,是Customers表的外键。代码如下:

 NorthwindEntities db = new NorthwindEntities();
var query = db.Customers.AsEnumerable();
for (int idx = ; idx < ; idx++)
{
var customer = query.ElementAt(idx);
var order = customer.Orders.FirstOrDefault();
if (order != null)
Console.WriteLine(order.OrderID);
}

在跟踪代码时,同时将SQL Server Profiler打开。代码执行到2行,sql跟踪器并没有执行sql语句。当执行第5行时,sql跟踪器有了反应。

sql 是查询了customers表。再往下执行到第6行时,

根据外键customerid 去查询orders订单。如此。每循环一次。数据库就会执行2次查询。如果有查询结果有20条,就会有40次查询,如果关联的表越多。查询的次数就会越多。

系统查询能不慢吗。

解决方法:

             NorthwindEntities db = new NorthwindEntities();
////取消EF的延迟加载
db.Configuration.LazyLoadingEnabled = false;
////一次性查询出customers和Orders数据,并利用ToList()放入到内存中
var query = db.Customers.Include("Orders").ToList();
for (int idx = ; idx < ; idx++)
{
var customer = query.ElementAt(idx);
var order = customer.Orders.FirstOrDefault();
if (order != null)
Console.WriteLine(order.OrderID);
}

取消EF的延迟加载。利用Include()将所需要对象一次性查询出来。并利用ToList()将数据存入内存中。

这是优化后的sql运行跟踪。我们会发现,只实现了一次查询,sql语句用了left join的方式将数据一次性查询出来。每次循环也只会访问内存中。

总结:

从这4行代码中,我们发现

1.AsEnumerable()和 AsQueryable() 是延迟执行,当具体使用对象时才会执行sql;ToList() 在使用时就已经执行,并数据存入内存中。
2.EF 本身默认的是延迟加载,每个关联的查询,每次循环的查询都是要执行数据库的。取消延迟加载,利用Include方法,可以一次性将所有数据查询出来。
以上观点纯属个人经验总结,欢迎各位大鸟发表看法,小菜向大家学习了。
 

【编后语】

博文发表后,笔者看到许多同行的讨论,也学到不少东西。笔者这里申明,自己并非黑EF。正是看到了EF的强大,才开始使用它。但是,任何东西都要学懂。就好比笔者来说,之前的用法,导致一个10行的列表,数据库查询就执行了好几百次。虽然这是在开发中问题不是很明显,但是一旦正式使用,这绝对是一个隐藏的炸弹。

EF很强大,但是,不懂它心的人,只会让自己伤心!

与广大程序员共勉!

【再编后语】

笔者很不平。多数同行并没有看懂这篇博文的意思。循环2次是模拟展示列表。例如,我有表格要展示这个客户的订单,没有分页。按照前面那种方案

 customer.Orders.FirstOrDefault();
这个客户有多少可订单,数据库执行多少次。
而第二种方案:
var query = db.Customers.Include("Orders").ToList();
数据库只执行一次就可以。展示表格的时候都是从内存中获取。
这就是是个明显数据库性能的问题。笔者虚心向大家讨教!

7行代码看EntityFramework是如何运行的更多相关文章

  1. Python 1行代码实现文本分类(实战笔记),含代码详细说明及运行结果

    Python 1行代码实现文本分类(实战笔记),含代码详细说明及运行结果 一.详细说明及代码 tc.py =============================================== ...

  2. 《第一行代码——Android》

    <第一行代码——Android> 基本信息 作者: 郭霖 丛书名: 图灵原创 出版社:人民邮电出版社 ISBN:9787115362865 上架时间:2014-7-14 出版日期:2014 ...

  3. 【转】【翻】Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏

    转自:http://mrfufufu.github.io/android/2015/07/01/Codelab_Android_Design_Support_Library.html [翻]Andro ...

  4. HTML5游戏实战(4): 20行代码实现FlappyBird

    这个系列很久没有更新了.几个月前有位读者调侃说,能不能一行代码做一个游戏呢.呵呵,接下来一段时间,我天天都在想这个问题,怎么能让GameBuilder+CanTK进一步简化游戏的开发呢.经过几个月的努 ...

  5. 通过 Mesos、Docker 和 Go,使用 300 行代码创建一个分布式系统

    [摘要]虽然 Docker 和 Mesos 已成为不折不扣的 Buzzwords ,但是对于大部分人来说它们仍然是陌生的,下面我们就一起领略 Mesos .Docker 和 Go 配合带来的强大破坏力 ...

  6. Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏

    原文:Codelab for Android Design Support Library used in I/O Rewind Bangkok session--Make your app fanc ...

  7. Android Studio 单刷《第一行代码》系列 01 —— 第一战 HelloWorld

    前言(Prologue) 本系列将使用 Android Studio 将<第一行代码>(书中讲解案例使用Eclipse)刷一遍,旨在为想入坑 Android 开发,并选择 Android ...

  8. Android Studio 单刷《第一行代码》系列 05 —— Fragment 基础

    前情提要(Previously) 本系列将使用 Android Studio 将<第一行代码>(书中讲解案例使用Eclipse)刷一遍,旨在为想入坑 Android 开发,并选择 Andr ...

  9. Android Studio 单刷《第一行代码》系列 03 —— Activity 基础

    前情提要(Previously) 本系列将使用 Android Studio 将<第一行代码>(书中讲解案例使用Eclipse)刷一遍,旨在为想入坑 Android 开发,并选择 Andr ...

随机推荐

  1. EF学习笔记-1 EF增删改查

    首次接触Entity FrameWork,就感觉非常棒.它节省了我们以前写SQL语句的过程,同时也让我们更加的理解面向对象的编程思想.最近学习了EF的增删改查的过程,下面给大家分享使用EF对增删改查时 ...

  2. MaxScript调用DotNet时命名空间的问题

    Fn GetSpecialFolder argEnumName = (DotNetClass "System.Environment").GetFolderPath (Execut ...

  3. LD算法的C++实现(基于编辑距离的文本比较算法)

    算法看这里: http://www.cnblogs.com/grenet/archive/2010/06/01/1748448.html 用数组实现: #include <iostream> ...

  4. Android Studio无法连接真机的问题?

    我不说,你可能又浪费半天时间,最后的结果,你可能还是没能解决!!! 现在,一般安卓手机为了安装软件方便,一般都安装了豌豆荚,但是,就是这个豌豆荚占用了Android Studio的ADB端口,导致An ...

  5. OCP 12c 062题库大更新,出现大量新题-5

    5.One of your databases supports an OLTP workload. The default undo tablespace is fixed size with: 1 ...

  6. 学习 swift (1)

    https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwi ...

  7. Webstorm 的 Tab 键怎样调整缩进值? 调节成缩进成2个空格或者4个空格

    原文:https://blog.csdn.net/niexia_/article/details/78280569 需求:因为用了eslint,对代码格式很严格.统一用空格.而用tab方式会省事很多. ...

  8. 使用request.js代理post失败的问题

    前面写过一篇使用request.js做代理的文章,可能眼睛敏锐的朋友已经看出在代理POST方法时和代理其它请求方式是有区别的, 现在我来说一下为什么要这么处理. 相信很多人都采用这种方式去代理POST ...

  9. python里面如何拷贝一个对象?deepcopy 和 copy 有什么区别 ?

    深拷贝就是说原内容改变但是拷贝的性内容不会改变,copy.copy和deepcopy对一个不可变类型进行拷贝, name结果相同都是浅拷贝指向引用如果是可变的话, 即使元组在最外层, 那么deepco ...

  10. C++ 定时器Timer在项目中的使用

    目录 1.情况说明 2.空循环实现 3.定时器实现 1.情况说明 由于最近要在项目里做弹出弹幕,要求是弹出1秒后消失,一开始我使用空循环进行计时,发现执行到这段代码CPU占用率上升十几个百分点,后来改 ...