Entity Framework中IQueryable, IEnumerable, IList的区别(转载)
原文:http://www.cnblogs.com/hiteddy/archive/2011/10/01/Difference_among_IQueryable_IEnumeralb_IList_in_Entity_Framework.html
使用工具追踪EF生成的SQL
使用Entity Framework等ORM框架的时候,SQL对于使用者来说是透明的,往往很多人也不关心ORM所生成的SQL,然而系统出现性能问题的时候就必须关注生成的SQL以发现问题所在。
使用过Toplink的朋友知道很只要设置日志打印级别=FINE就可以配置使之生成的SQL在服务器中打印出来,Entiry Framework没有那么幸运,在以前要检测生成SQL的唯一方法是SQL Server Profiler,但使用起来并不方便,结果也不能自动保存到文件中。
Tracing and Caching Provider Wrappers for Entity Framework是Entity Framework Team新推出的开源SQL追踪和二级缓存的解决方案。原理是在负责执行具体SQL语句的data provider(SqlClient或者其他Client)之上插入了一层WrappingProvider,用于监控 DbCommand.ExecuteReader(), ExecuteScalar() and ExecuteNonQuery(),将Sql命令输出到指定介质或者将查询结果缓存起来以重用。
使用方法很简单,下载源代码编译后将dll添加到项目中,新加一个类WrappedNorthWindEntities继承原有的Entities即可,详见源代码中的示例。

测试IQueryable, IEnumerable, IList的区别
下面我们使用EF Wrapper来监测Entify Framework中IQueryable, IEnumerable和IList所生成的SQL。

private static void TestIQueryable()
{
using (var ctx = new WrappedNorthWindEntities())
{
IQueryable<Product> expression = ctx.Products.Take();
IQueryable<Product> products = expression.Take(); // A 不执行SQL
Console.WriteLine(products.Count()); // B SELECT COUNT(1) FROM ( SELECT TOP (2) * FROM ( SELECT TOP (5) * FROM [dbo].[Products] ))
Console.WriteLine(products.Count()); // C SELECT COUNT(1) FROM ( SELECT TOP (2) * FROM ( SELECT TOP (5) * FROM [dbo].[Products] ))
foreach (Product p in products) // D SELECT TOP (2) * FROM ( SELECT TOP (5) * FROM [dbo].[Products]
{
Console.WriteLine(p.ProductName);
}
foreach (Product p in products) // E SELECT TOP (2) * FROM ( SELECT TOP (5) * FROM [dbo].[Products] )
{
Console.WriteLine(p.ProductName);
}
}
}


private static void TestIEnumerable()
{
using (var ctx = new WrappedNorthWindEntities())
{
IEnumerable<Product> expression = ctx.Products.Take().AsEnumerable();
IEnumerable<Product> products = expression.Take(); // A 不执行SQL
Console.WriteLine(products.Count()); // B SELECT TOP (5) * FROM [dbo].[Products]
Console.WriteLine(products.Count()); // C SELECT TOP (5) * FROM [dbo].[Products]
foreach (Product p in products) // D SELECT TOP (5) * FROM [dbo].[Products]
{
Console.WriteLine(p.ProductName);
}
foreach (Product p in products) // E SELECT TOP (5) * FROM [dbo].[Products]
{
Console.WriteLine(p.ProductName);
}
}
}


private static void TestIList()
{
using (var ctx = new WrappedNorthWindEntities())
{
var expression = ctx.Products.Take();
IList<Product> products = expression.Take().ToList(); // A SELECT TOP (2) * FROM ( SELECT TOP (5) * FROM [dbo].[Products] Console.WriteLine(products.Count()); // B 不执行SQL
Console.WriteLine(products.Count()); // C 不执行SQL
foreach (Product p in products) // D 不执行SQL
{
Console.WriteLine(p.ProductName);
}
foreach (Product p in products) // E 不执行SQL
{
Console.WriteLine(p.ProductName);
}
}
}

测试结果
- IQueryable和IEnumerable都是延时执行(Deferred Execution)的,而IList是即时执行(Eager Execution)
- IQueryable和IEnumerable在每次执行时都必须连接数据库读取,而IList读取一次后,以后各次都不需连接数据库。前两者很容易造成重复读取,性能低下,并且可能引发数据不一致性
- IQueryable和IEnumerable的区别:IEnumberalb使用的是LINQ to Object方式,它会将AsEnumerable()时对应的所有记录都先加载到内存,然后在此基础上再执行后来的Query。所以上述TestIEnumerable例子中执行的SQL是"select top(5) ...",然后在内存中选择前两条记录返回。
以下是一个IQueryable引发数据不一致性的例子:记录总数和记录详情两者本应一致,但由于IQueryable前后两次读取数据库,结果是现实有10条记录,却输出11条详情。

IQueryable<Product> products = ctx.Products.All();
//开始的时候数据库product表中有10条记录, count = 10
int count = products.Count();
Console.WriteLine("Count of products:"+count);
//此时另一进程添加一个产品进数据库
//会重新读取数据库并输出11个产品名称
foreach (Product p in products)
{
Console.WriteLine(p.ProductName);
}

结论
基于性能和数据一致性这两点,我们使用IQueryable时必须谨慎,而在大多数情况下我们应使用IList。
- 当你打算马上使用查询后的结果(比如循环作逻辑处理或者填充到一个table/grid中),并且你不介意该查询会即时执行,使用ToList()
- 当你希望查询后的结果可以供调用者(Consummer)作后续查询(比如这是一个"GetAll"的方法),或者你希望该查询延时执行,使用AsQueryable()
Entity Framework中IQueryable, IEnumerable, IList的区别(转载)的更多相关文章
- Entity Framework中IQueryable, IEnumerable, IList的区别[转]
使用工具追踪EF生成的SQL 使用Entity Framework等ORM框架的时候,SQL对于使用者来说是透明的,往往很多人也不关心ORM所生成的SQL,然而系统出现性能问题的时候就必须关注生成的S ...
- Entity Framework中IQueryable, IEnumerable, IList的区别
博客园里有这样的总结.这里姑且先列个题目, 提醒自己记忆.
- Entity Framework中使用IEnumerable<T>、IQueryable<T>及IList<T>的区别
1. IEnumerable<T> IEnumerable<T> :对于在内存中集合上运行的方法,返回的可枚举对象将捕获传递到方法的参数.在枚举该对象时,将使用查询运算符的逻辑 ...
- Entity framework 中Where、First、Count等查询函数使用时要注意
在.Net开发中,Entity framework是微软ORM架构的最佳官方工具.我们可以使用Lambda表达式在Entity framework中DbSet<T>类上直接做查询(比如使用 ...
- Entity Framework 教程——Entity Framework中的实体类型
Entity Framework中的实体类型 : 在之前的章节中我们介绍过从已有的数据库中创建EDM,它包含数据库中每个表所对应的实体.在EF 5.0/6.0中,存在POCO 实体和动态代理实体两种. ...
- [转]在Entity Framework中使用LINQ语句分页
本文转自:http://diaosbook.com/Post/2012/9/21/linq-paging-in-entity-framework 我们知道,内存分页效率很低.并且,如果是WebForm ...
- Lazy<T>在Entity Framework中的性能优化实践
Lazy<T>在Entity Framework中的性能优化实践(附源码) 2013-10-27 18:12 by JustRun, 328 阅读, 4 评论, 收藏, 编辑 在使用EF的 ...
- 关于Entity Framework中的Attached报错相关解决方案的总结
关于Entity Framework中的Attached报错的问题,我这里分为以下几种类型,每种类型我都给出相应的解决方案,希望能给大家带来一些的帮助,当然作为读者的您如果觉得有不同的意见或更好的方法 ...
- 关于Entity Framework中的Attached报错的完美解决方案终极版
之前发表过一篇文章题为<关于Entity Framework中的Attached报错的完美解决方案>,那篇文章确实能解决单个实体在进行更新.删除时Attached的报错,注意我这里说的单个 ...
随机推荐
- C语言中的字符串处理库函数介绍与实现
一.介绍 本文将主要介绍字符串处理库函数中的strlen.strcpy.strcat.strcmp.atoi等,主要由<string.h>头文件提供. 二.strlen函数:求字符串的长度 ...
- Linux 目录结构_004
前言 Linux文件系统层次标准,英文全称Filesystem Hierarchy Standard,英文简称FHS. 由于利用Linux来开发产品的团队和个人实在太多了,如果每个人都以自己的想法来配 ...
- Ubuntu下安装和使用zookeeper和kafka
1.在清华镜像站下载kafka_2.10-0.10.0.0.tgz 和 zookeeper-3.4.10.tar.gz 分别解压到/usr/local目录下 2.进入zookeeper目录,在conf ...
- iOS开发之--宏定义与const的区别及使用方法
宏定义的常见用法: 定义一段代码,或指定字符串抽成宏. const(常量): 当有字符串常量的时候,苹果推荐我们使用const,苹果经常把常用的字符串定义成const 宏定义与const的区别: 编译 ...
- IntelliJ IDE破解
1.购买正版用户 2.激活码 一:下载以下jar,放到 bin 破解补丁无需使用注册码,下载地址 idea14 keygen下载地址 二:在下面两个文件中加入-javaagent:E:\IDEA\In ...
- 关于JSON call 的一个小问题
如图当我们在做Json call 的时候,一定要切记,建立的model 一定要与JSON 字符串严格的一一对应,否者会解析不出来
- 6.18_web服务器内容
#coding:utf-8 ''' 2018-6-18 14:47:23 创建一个静态服务器访问指定页面 http://127.0.0.1:8000/ ''' import socket from m ...
- cmus 命令行播放器使用
安装 sudo eopkg it cmus 启动 cmus 设置输出 :set output_plugin=pulse 导入本地音乐 :add /home/your_username/Music 查看 ...
- eclipse启动报错:Could not create the java virtual machine
用maven.springboot开发时,安装了当时最新版的eclipse(3.5.5).eclipse解压版的非常方便,想先安装了看看.暂时没有升级其他软件. 打开的时候报错: 原因其实就是还木有升 ...
- TOP100summit2017:Riot Games 李仁杰——大数据落地要找到数据和经验的平衡点
壹佰案例:李仁杰老师您好,很荣幸您能参加第六届TOP100全球软件案例研究峰会,您在大数据和人工智能领域有非常丰富的经验,在这次大会上您将分享什么内容? 李仁杰:这次我主要分享的有两个方面. 一个 ...