Entity Framework中IQueryable, IEnumerable, IList的区别
来源:互联网 发布:知乎是什么时候成立的 编辑:程序博客网 时间:2024/04/26 15:07
Entity Framework中IQueryable, IEnumerable, IList的区别
使用工具追踪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(5); IQueryable<Product> products = expression.Take(2); // 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(5).AsEnumerable(); IEnumerable<Product> products = expression.Take(2); // 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(5); IList<Product> products = expression.Take(2).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()
转自:http://www.cnblogs.com/hiteddy/archive/2011/10/01/Difference_among_IQueryable_IEnumeralb_IList_in_Entity_Framework.html
- Entity Framework中IQueryable, IEnumerable, IList的区别
- Entity Framework中IQueryable, IEnumerable, IList的区别
- Entity Framework中IQueryable, IEnumerable, IList的区别
- Entity Framework中使用IEnumerable<T>、IQueryable<T>及IList<T>的区别
- Entity Framework返回IEnumerable还是IQueryable?
- Entity Framework返回IEnumerable还是IQueryable?
- IEnumerable, IQueryable的区别
- Entity Framework--IQueryable与IEnumberable的区别
- Entity Framework:IQueryable与IEnumberable的区别
- IEnumerable和IQueryable的区别
- IQueryable和IEnumerable的区别
- IQueryable和IEnumerable的区别
- IList,ICollection,IEnumerable,IEnumerator,IQueryable
- IList,ICollection,IEnumerable,IEnumerator,IQueryable
- 关于IList、IQueryable、IEnumerable与Func、Expression的关系
- Entity Framework快速入门--IQueryable与IEnumberable的区别
- Entity Framework快速入门--IQueryable与IEnumberable的区别
- Entity Framework快速入门--IQueryable与IEnumberable的区别
- 减少C++代码编译时间的方法
- 黑马程序员————C语言——基本语法3
- 社説 20150323 公示地価 街の魅力向上で回復を地方に
- Spring3.0中的AOP(二)
- iOS8 学习新技术
- Entity Framework中IQueryable, IEnumerable, IList的区别
- Cocos2d-x 3.1 Lua Binding
- 社説 20150323 国連防災会議 「仙台枠組み」で被害の抑制を
- ios xmpp探索研究:了解什么是XMPP协议
- Python正则表达式的用法
- 图片上传方法
- TextRenderer.MeasureText计算字符串文本所占的尺寸
- Mac上 python 找不到 yaml模块
- 读取bmp图片