概要

我们在应用开发中经常用到IQueryable 和 IEnumerable两个接口。如果这两个接口搞混,往往会对程序性能造成很大的影响。

本文以一个实例来区分这两个接口,说明在实际开发过程中,这两个接口如何使用,尤其是IQueryable 和接口IEnumerable中的LINQ扩展方法的使用。

基本定义

IEnumerable
IEnumerable 是一个接口,客户代码通过实现该接口的GetEnumerator方法,来返回一个具体的IEnumerator.。

在实际应用中,IEnumerable 面向内存对象,它会将所有的数据载入到内存中,再进行各种操作。IEnumerable 包含一系列操作内存对象的扩展方法。

IQueryable
IQueryable 是一个接口,一般通过第三方的Data Provider来实现接口中的方法。例如EntityFramework。

在实际应用中,IQueryable 面向Data Provider,为其创建查询的SQL语句。

实例说明

本文通过一个使用EntityFramework来查询农业银行在天津的分行数据,来说明两个接口在实际使用中的差别。

IEnumerable获取数据

关键代码如下:

 using (var context = new BranchContext(connectionString)){IEnumerable<Branch> branches = context.Branches.Where( b => b.Id > 1);branches = branches.Take(2);foreach(Branch branch in branches){System.Console.WriteLine(branch.Name);}}

运行结果如下:

结果分析:

  1. SQL语句中只有Id >1 一个过滤条件。
  2. 数据库查询后,所有的查询结果全部载入内存IEnumerable对象中。
  3. IEnumerable的Take方法在内存中过滤出前两个分行数据,并显示。

IQueryable 获取数据

关键代码如下:

using (var context = new BranchContext(connectionString)){IQueryable<Branch> branches = context.Branches.Where( b => b.Id > 1);branches = branches.Take(2);foreach(Branch branch in branches){System.Console.WriteLine(branch.Name);}
}

运行结果如下:

结果分析:

  1. SQL语句中既有Id >1 一个过滤条件,又有top关键字过滤前两个查询结果。
  2. 第一条语句执行后,IQueryable只是为EntityFramework生成了查询语句,过滤条件是Id>1,并没有真正进行数据库查询。
  3. 第二条Take语句执行后, IQueryable为EntityFramework重新生成了查询语句,包括了top部分。
  4. Foreach语句触发了数据库查询,所以我们看到的SQL即包含Id > 1的过滤条件,又包含了top语句。

结论

IEnumerable中的Linq查询方法,只是针对内存对象。IQueryable中的Linq查询方法,是帮助第三放Data Provider生成查询的SQL语句。

所以我们在做大数据表服务器端分页操作时候,一定要小心。我们必须确保所有的查询方法都是基于IQueryable的,最后都能反应到SQL语句上。避免由于不慎使用 IEnumerable,将大数据表全部载入内存,再进行各种过滤操作的情况。那样做,会使服务器压力激增。

附录

完整C#代码

Branch.cs

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace IQueryableIEnumerable
{[Table("t_branch")]public class Branch{[Required]public int Id { get; set; }[Required]public string Name { get; set; }[Required, Column("Addr")]public string Address { get; set; } [Timestamp]public byte[] RowVersion { get; set; }}
}

BranchContext.cs

using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace IQueryableIEnumerable
{public class BranchContext : DbContext {private readonly ILoggerFactory loggerFactory = LoggerFactory.Create(ConventionForeignKeyExtensions => ConventionForeignKeyExtensions.AddConsole());private readonly string ConnectionString;public DbSet<Branch> Branches {get;set;}public BranchContext(string connectionString){ConnectionString = connectionString;}protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){optionsBuilder.UseLoggerFactory(loggerFactory);optionsBuilder.UseSqlServer(ConnectionString);}}
}

Main 函数

using System;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Collections.Generic;
namespace IQueryableIEnumerable
{class Program{static void Main(string[] args){var connectionString = @"Server=PC-20210618NEZE\SQL2012EXPRESS;Database=BranchMngt;Trusted_Connection=True;MultipleActiveResultSets=true";using (var context = new BranchContext(connectionString)){IQueryable<Branch> branches = context.Branches.Where( b => b.Id > 1);branches = branches.Take(2);foreach(Branch branch in branches){System.Console.WriteLine(branch.Name);}} /* using (var context = new BranchContext(connectionString)){IEnumerable<Branch> branches = context.Branches.Where( b => b.Id > 1);branches = branches.Take(2);foreach(Branch branch in branches){System.Console.WriteLine(branch.Name);}} */}}
}

SQL建表语句和数据初始化

if object_id(N't_branch',N'U') is not null drop table t_branchcreate table t_branch (Id int primary key identity(1,1),Name nvarchar(50) not null,Addr nvarchar(200) not null,[RowVersion] [timestamp] NULL)insert into t_branch (Name,Addr) values(N'天津丽江道支行',N'天津市西青区李七庄街凌口村悦雅花园9号楼底商一层'),(N'中国农业银行',N'天津市南开区凌宾路'),(N'天津宾水西道支行',N'天津市南开区宾水西道阳光公寓A座首层、二层'),(N'天津李七庄支行',N'天津市河西区纪庄子道4号'),(N'天津阳光支行',N'天津市南开区港宁西路27号'),(N'环湖中路支行',N'天津市河西区环湖中路10号(13路终点站)')

C#中的IQueryable vs IEnumerable相关推荐

  1. IQueryable 和 IEnumerable

    IQueryable 和 IEnumerable 其实,对于上面的即有过虑又有排序的条件查询Linq语句,EF是读取数据库中整个Books表中的数据到内存,还是根据Linq查询语句智能的生成SQL再执 ...

  2. IQueryable和IEnumerable区别

    IQueryable 和IEnumerable总结 1,IEnumerable<T> result = (from t in context.Table  order by t.Id se ...

  3. IQueryable和IEnumerable,IList的区别

    IQueryable和IEnumerable都是延时执行(Deferred Execution)的,而IList是即时执行(Eager Execution) IQueryable和IEnumerabl ...

  4. IQueryable和IEnumerable学习

    IQueryable和IEnumerable区别 开始了解IQueryable和IEnumerable前,我们先看一下源码 由上面的图片可以得知IQueryable接口继承自IEnumerable接口 ...

  5. 对IQueryable和IEnumerable的认识

    ** IQueryable和IEnumerable的区别 public static IQueryable<TSource> Where<TSource>(this IQuer ...

  6. C# IQueryable 和 IEnumerable 的区别

    这是 EF Core 系列的最后一篇文章,按照上一篇的计划,我们最后就讲一讲 IQueryable 和 IEnumerable 的区别. 点击上方或后方蓝字,阅读 EF Core 系列合集. 在前面的 ...

  7. 【C#】IQueryable和IEnumerable的区别

    IEnumerable接口 公开枚举器,该枚举器支持在指定类型的集合上进行简单迭代.也就是说:实现了此接口的object,就可以直接使用foreach遍历此object: IQueryable 接口 ...

  8. IQueryable 和 IEnumerable 的区别

    在C#中使用 Linq to sql 时,经常搞混 IQueryable 和 IEnumerable 这两种类型,本文简单分析下它们之间的区别和使用场景. 前言 不管是Linq to object,还 ...

  9. EFCore——IQueryable与IEnumerable的区别(13)

    IQueryable与IEnumerable的区别 一.IQueryable与IEnumerable的简单实例 二.IQueryable与IEnumerable的区别 一.IQueryable与IEn ...

最新文章

  1. 投影串口测试程序_【原创】串口通信测试程序
  2. 超酷图片压缩工具,就是不支持批量
  3. VS与Win7 共舞:用户界面特权隔离
  4. h5手机端浏览器机制_H5测试介绍
  5. Executor 执行器接口笔记
  6. 【深度学习】解决物体检测中的小目标问题
  7. The TensorFlow library wasn‘t compiled to use SSE instructions, but these are available on your mach
  8. MySQL Performance-Schema(二) 理论篇
  9. synchronized锁的升级
  10. js高级编程_这位设计师用Processing把创意编程玩到了极致!
  11. 信息加密之信息摘要加密MD2、MD4、MD5
  12. python中scrapy是什么_python爬虫中scrapy组件有哪些?作用是什么?
  13. 蓝桥杯 ADV-158 算法提高 新建Microsoft Word文档
  14. Learning to Ranking
  15. 小米/VIVO/OPPO全系列救砖+解锁+工具+教程+激活账户技术
  16. c语言程序设计操作,c语言编程入门相关详细操作
  17. MMDetection学习教程(一)
  18. Docker-禁用userland代理
  19. LINUX中DNS服务器反向解析
  20. 有符号数和无符号数在计算机中怎么区分?

热门文章

  1. IPSec—IKE协议介绍
  2. 数据库课程设计————学生考试系统
  3. 文件共享及磁盘管理_01
  4. MySQL 获取当前时间
  5. Nginx配置正向代理
  6. artdialog ajax,GitHub - xiaok/artDialog: 优雅的web对话框控件
  7. SQL注入之sql-labs-Less3~Less37
  8. 计算机控制技术课程综述,胡计算机控制技术课程综述.doc
  9. 建立邮件列表的九种主要资源
  10. Ubuntu重启网卡的三种方法