概要

我们在应用开发中经常用到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. FEMS:微生物群落生态学数据挖掘的R包microeco
  2. 蚂蚁金服付志嵩:数据膨胀?关系复杂?如何升级图数据库?
  3. 二分查找之搜索插入位置
  4. 2054无法登陆mysql_张虹亮'blog » ubuntu20.04安装mysql8之后,php5程序和phpmyadmin出现#2054 无法登录MySQL服务器的解决方案...
  5. RHEL 6.5----haproxy实现负载均衡
  6. ArcGIS.Server.9.2.DotNet实现EditorTask功能扩展(自带例子 十、三)
  7. php打印当前页面隐藏页眉,javascript实现window.print()去除页眉页脚_javascript技巧
  8. 《高质量C编程指南》读后感
  9. illegal multibyte sequence 解决方法
  10. Kotlin语言内置函数学习2:with,also,takeIf,takeUnless
  11. vue中prop的用法
  12. 抖音爆火微信每日早安推送
  13. SQL获取当前月份的第一天
  14. 利用光盘安装linux系统
  15. 谷歌浏览器本地HTML文件无法打开
  16. Python3中的多态 ,鸭子类型
  17. 在中国当程序员,35岁是分水岭?这些新路你知道吗?
  18. R语言使用levels参数重新排序因子水平级别
  19. 【ArcGIS Runtime SDK for Android-00】具备怎样的能力
  20. 压缩文件提示操作被计算机限制,压缩文件不能解压

热门文章

  1. Microsoft LDAP 配置页中输入有效的用户名及密码,microsoft ldap 配置页中输入有效的用户名
  2. 大数据技术之Hadoop分布式文件系统HDFS系统知识整理(从入门到熟练操作)
  3. go zap日志库的使用,以及封装。
  4. Django—DetailView
  5. 电脑怎么查看磁盘空间?磁盘不足怎么清理?
  6. Directory和DirectoryInfo区别
  7. erlang rpc 远程调用
  8. 基于Java敬老院管理系统的设计与实现
  9. JSON-初识+解析
  10. VIBRO-METER VM600 IRC4 可在螺丝端子连接器上获得