使用工具追踪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。

TestIQueryableprivate static void TestIQueryable()
{using (var ctx = new WrappedNorthWindEntities()){IQueryable<Product> expression = ctx.Products.Take(5);IQueryable<Product> products = expression.Take(2);   // A  不执行SQLConsole.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);}}
}

TestIEnumerableprivate static void TestIEnumerable()
{using (var ctx = new WrappedNorthWindEntities()){IEnumerable<Product> expression = ctx.Products.Take(5).AsEnumerable();IEnumerable<Product> products = expression.Take(2);  // A  不执行SQLConsole.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);}}
}

TestIListprivate 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 不执行SQLConsole.WriteLine(products.Count());            // C  不执行SQLforeach (Product p in products)               // D  不执行SQL
        {Console.WriteLine(p.ProductName);}foreach (Product p in products)                // E  不执行SQL
        {Console.WriteLine(p.ProductName);}}
}

测试结果

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

以下是一个IQueryable引发数据不一致性的例子:记录总数和记录详情两者本应一致,但由于IQueryable前后两次读取数据库,结果是现实有10条记录,却输出11条详情。

IQueryable Data InconsistancyIQueryable<Product> products = ctx.Products.All();//开始的时候数据库product表中有10条记录, count = 10int 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()

转载于:https://www.cnblogs.com/caoheyang911016/p/3178886.html

Entity Framework中IQueryable, IEnumerable, IList的区别(转自网络)相关推荐

  1. Entity Framework中IQueryable, IEnumerable, IList的区别

    使用工具追踪EF生成的SQL 使用Entity Framework等ORM框架的时候,SQL对于使用者来说是透明的,往往很多人也不关心ORM所生成的SQL,然而系统出现性能问题的时候就必须关注生成的S ...

  2. 如何处理Entity Framework中的DbUpdateConcurrencyException异常

    如何处理Entity Framework中的DbUpdateConcurrencyException异常 参考文章: (1)如何处理Entity Framework中的DbUpdateConcurre ...

  3. 在Entity Framework中使用存储过程(一):实现存储过程的自动映射

    之前给自己放了一个比较长的假期,在这期间基本上没怎么来园子逛.很多朋友的留言也没有一一回复,在这里先向大家道个歉.最近一段时间的工作任务是如何将ADO.NET Entity Framework 4.0 ...

  4. Entity Framework中的Migrations

    Migrations是Entity Framework中非常有意思的一个工具.Migrations 的目的是用来跟踪数据库的改变. 假如我们想回滚到一个月前的代码,非常容易,有版本管理工具.但是要回滚 ...

  5. 关于Entity Framework中的Attached报错相关解决方案的总结

    关于Entity Framework中的Attached报错的问题,我这里分为以下几种类型,每种类型我都给出相应的解决方案,希望能给大家带来一些的帮助,当然作为读者的您如果觉得有不同的意见或更好的方法 ...

  6. C#中List与IList的区别

    C#中List与IList的区别 2009-11-15 14:19 List<T>类:表示可通过索引访问的对象的强类型列表,提供用于对列表进行搜索.排序和操作的方法. IList<T ...

  7. 在Entity Framework中使用事务

    继续为想使用Entity Framework的朋友在前面探路,分享的东西虽然技术含量不高,但都是经过实践检验的. 在Entity Framework中使用事务很简单,将操作放在TransactionS ...

  8. List<T>, IQueryable, IEnumerable 关系和区别

    最近在修项目的历史代码,发现搞混了很多拓展方法,写一篇博客澄清一下. 概念需要:iqueryable不应该和ienumerable比而应该和ilist比,ienumerable是这两者的父接口. 问题 ...

  9. 【转】学习Entity Framework 中的Code First

    这是上周就写好的文章,是在公司浩哥的建议下写的,本来是部门里面分享求创新用的,这里贴出来分享给大家. 最近在对MVC的学习过程中,接触到了Code First这种新的设计模式,感觉很新颖,并且也体验到 ...

最新文章

  1. php获取栏目文章总数,织梦DedeCMS获取当前栏目文章数量
  2. 使用IDA Pro动态调试SO文件
  3. websocket一直无法链接_.NET Core 实现基于Websocket的在线聊天室
  4. Ubuntu下 VirtualBox的卸载和升级 (转载)
  5. python 配置文件对比_Python3实现配置文件差异对比脚本
  6. HibernateEHCache –Hibernate二级缓存
  7. fit函数 model_函数式 API
  8. Aspose.Words从零创建OOXML图表
  9. CSS控制显示超出部分,用省略号显示
  10. debian查询端口进程_Linux入门-端口和进程号
  11. 缓存框架 EhCache 使用 2
  12. 大众点评字体反爬解析
  13. 求一个向量变换为另一个向量的矩阵_机器学习数学-矩阵
  14. Redis基本知识记录
  15. python去掉json中的转义符_企业微信表情符自动转义怎么用?企业微信电脑版这样做...
  16. Spark的容错机制
  17. java调用shell脚本,解决传参和权限问题
  18. 极点输入法如何关闭单过了模式
  19. 为了进大厂,韩顺平高级Java教程百度云
  20. JavaWeb 入门

热门文章

  1. 一梦江湖卡在获取服务器信息,一梦江湖小技巧,不氪金,卡级玩家怎么获取资源提升修为...
  2. android的快速开发框架,FastAndroid
  3. Linux的shell脚本实战之检查主机IP是否存在
  4. Java高并发编程(六):重入锁
  5. 深入理解JVM虚拟机(二):垃圾回收机制
  6. 一周一论文(翻译)—— [PVLDB 12] Distributed GraphLab A Framework for Machine Learning 分布式机器学习图计算框架
  7. python服务器搭建ftp_Python搭建HTTP服务器和FTP服务器
  8. html表单上传图片获取路径,asp.net获取HTML表单File中的路径的方法
  9. python以某种编码进行打印_如何在一场面试中展现你对Python的coding能力?
  10. Vue 组件中 移动 this.$el 的注意事项