Entity Framework数据加载时的性能问题

今天发现网站的速度慢的出奇,当时用EF的时候也没怎么注意,加载数据时随心所欲,对EF的原理不是很清楚。使用EF的目的只有一个,那就是快!

下面也是在网上搜到的一些内容,进行了整合。有些说的也不一定对,望路过者给点补充。

 

在EF下有三个对象IQueryable,IEnumerable以及IList,这些接口都可以使用数据查询操作,但是有一些问题需要明白。
http://www.cnblogs.com/hiteddy/archive/2011/10/01/Difference_among_IQueryable_IEnumeralb_IList_in_Entity_Framework.html


IEnumerable对象一旦AsEnumerable后总是需要到数据库中获取数据源,
(每次都如此),然后把数据源加载到内存中后,再执行Linq to Object的操作,所以后续就只在内存中完成了。
 
IQueryable对象则更严重,几乎每个数据操作都会到数据库中获取数据,但是它可以把这些操作组成一个复杂的表达式,一次完成。也就是说,它会把这些查询操作记下来,到真正索取数据时一下子都返回,这会生成一个很复杂的sql语句,不过sql server都有计划任务,肯定会被优化的。
 
IList数据,基本上只要ToList了,马上就会加载数据源,以后的操作就跟数据库没关了,全部在内存中完成。
 


一个性能杀手:
http://www.cnblogs.com/dudu/archive/2012/04/01/enitity_framework_func.html


在IQuerable中使用Func参数,会引起的数据库全表查询。如
public List<Steel> GetOne(Func<T, bool> predicate){
   this.context.Steels.Where(predicate).ToList();
}
将会导致Steel全表查询,将整个数据集加载到内存中。
原因是以上操作会导致this.context.Steels转换为IEnumerable,这就意味着一次AsEnumrable方法调用,致使加载所有数据集到内存中。
解决办法是把predicate参数换成Expression<Func<T,bool>> predicate即可。这样的话会使用IQueryable方法调用Where语句。
这里要强调的是,上述GetOne里的Where语句,可以是IEnumerable的Where方法,也可以是IQueryable的Where方法。this.Context.Steels是
DbSet对象,该对象实现了IEnumerable和IQueryable接口,故Where语句里的参数是Func还是Expression将决定DbSet对象的转换。
 
 使用MiniProfiler进行性能调试

这个工具在MVC和EF架构的网站中,非常适用检验网站性能。使用NuGet下载MiniProfiler和MiniProfilerEF,具体过程可以在网上搜下。我在使用时遇到的一个问题是,总是输不出调试信息来。使用EF4.1以后的版本可以解决这个问题,所以如果你调试的不顺利,建议升级EF到4.3,应该不会出错了。

 

我使用MiniProfiler检查出大量由于LazyLoading带来的性能问题,有时候一个数据量较多的页面,sql请求可能超过上百个。LazyLoading并不总是那么好,对于在网页中总是要显示的数据,不妨一下子都加载进来,然后在内存中找到需要的数据再使用。

 


 
 

 

posted @ 2012-06-06 16:48  Zigzag  阅读(1560)  评论(0编辑  收藏  举报