C# :IQueryable IEnumerable

文章目录

  • 1. IEnumerable
  • 2. IQueryable
  • 3. LINQ to SQL
  • 4. IEnumerable & IQueryable
    • 4.1 Expression
    • 4.2 Provider

image.png

1. IEnumerable

namespace System.Collections:
public interface IEnumerable
{public IEnumerator GetEnumerator ();
}public interface IEnumerator
{pubilc object Current { get; }public bool MoveNext ();public void Reset ();
}

IEnumerable 只有一个方法 GetEnumerator(), 既实现IEnumerable的所有泛型集合,都具备可枚举(IEnumerator)的能力

IEnumerator 只有一个属性 Current,和两个方法 MoveNext() \ Reset()

通过 MoveNext()Current 可以不停地移动 enumerator 的位置并返回当前的元素。

Reset() 会将 enumerator 设置到初始位置,既第一个元素之前

2. IQueryable

namespace System.Linq:public interface IQueryable<out T> : System.Collections.Generic.IEnumerable<out T>, System.Linq.IQueryable {}public interface IQueryable : System.Collections.IEnumerable
{// 表达式树返回结果的元素类型public Type ElementType { get; }// 获取IQueryable实例的表达式树public System.Linq.Expressions.Expression Expression { get; }public System.Linq.IQueryProvider Provider { get; }
}// 定义用于创建和执行IQueryable对象所描述的查询的方法
public interface IQueryProvider
{public System.Linq.IQueryable CreateQuery(System.Linq.Expressions.Expression expression);public System.Linq.IQueryable<TElement> CreateQuery<TElement> (System.Linq.Expressions.Expression expression);public object? Execute(System.Linq.Expressions.Expression expression);public TResult Execute<TResult> (System.Linq.Expressions.Expression expression);
}

IQueryable 继承 IEnumerable,所以 IQueryable 具备可枚举的能力。

IQueryable 中的 Expession / Provider 则用来实现LINQ to SQL,具体可以看接下来的2节详细解释。

3. LINQ to SQL

LINQ to SQL是.Net Framework v3.5的组件,是能够提供将关系数据作为对象管理的运行时基础结构。

以往,编程语言通过 API 访问数据库数据的时候,需要将查询语句转为文本字符串。LINQ to SQL则会将对象模型中的语言集成查询转换为SQL,并发给数据库执行。当返回结果时,LINQ to SQL会再转换回可以用编程语言处理额对象。

所以,当拥有一个查询的时候,并不意味着查询已经执行:

var q = from c in dbContext.Customers Where c.City == ":London" select c;

命令对象会保留描述查询的字符串,IQueryable 对象的 Expression。命令对象的 ExecuteReader() 方法执行后,以 DataReader 形式返回结果。IQueryable 对象通过 GetEnumerator() 方法返回 IEnumerator 结果。

如下 foreach 会执行两次 query,这种行为成为延迟执行

var q =from c in db.Customerswhere c.City == "London"select c;
// Execute first time
foreach (Customer c in q)Console.WriteLine(c.CompanyName);
// Execute second time
foreach (Customer c in q)Console.WriteLine(c.CompanyName);

如果提前将结果转为任意标准的集合类,可以避免重复执行。

var q =from c in db.Customerswhere c.City == "London"select c;
// Execute once using ToList() or ToArray()
var list = q.ToList();
foreach (Customer c in list)Console.WriteLine(c.CompanyName);
foreach (Customer c in list)Console.WriteLine(c.CompanyName);

更多资料:LINQ:.NET Language-Integrated查询

4. IEnumerable & IQueryable

4.1 Expression

针对 IEnumerable所设计的扩展方法都将表达式视为委托,而针对 IQueryable 的那些扩展方法用的则是表达式树(expression tree)

IQueryable 会解析表达式树,并把这棵树表示的逻辑转为 provider 能够操作的格式,将其放在离数据最近的地方去执行。即传输数据往往会少于 IEnumerable,总体性能更好。

借鉴 《Effective C#》中的例子,如下两种写法,返回的结果相同,但是工作方式却不同:

// 1. use IQueryable
var q = from c in dbContext.Customers Where c.City == ":London" select c;
var finalAnswer = from c in q ordery c.Name select c;// 2. use Enumerable
var q = (from c in dbContext.Customers where c.City == "London" select c).AsEnumerable();
var finaAnswer = from c in q orderby c.Name select c;

方法1,采用的是 IQueryable内置的 LINQ to SQL,q的查询语句,会和 第二行的组合起来,即只需要向数据库发送一次调用,where和orderby会在同一次sql查询操作里完成

方法2,则是把数据库对象从 IQueryable 强制转为了 IEnumerable形式的标准可枚举对象,即先向数据库发送查询请求,获得所有的数据后,放在本地进行排序操作

假如每种方法第二行还有一次 where 筛选一部分数据,那么方法1会组合2次 where,数据库只会返回最终目标数据集。而方法2会先从数据把所有第一次 where 得到的数据传到本地,之后在本地再次筛选,无疑增加了网络数据传输量。

4.2 Provider

IQueryable 的 Provider 未必能支持每一种查询方式,只能支持某些固定的运算符、方法,所以一旦查询操作里面调用除此之外的方法,那么就有可能把序列当成 IEnumerable 来查询,而非 IQueryable,否则会抛出异常。

再上 《Effective c#》例子:

private bool isValidProduct(Product p) => p.ProductName.LastIndexOf('C') == 0;// 1. 转为 Enumerable 执行
var q1 = from p in dbContext.Products.AsEnumerable() where isValidProduct(p) select p;// 2. 直接执行 IsValidProduct
var q2 = from p in dbContext.Products where isValidProduct(p) select p;

方法1可以正常运行,只是在 AsEnumerable() 之后,查询必须在本地执行,where 字句内的逻辑由LINQ to Objects处理。

方法2则会抛出异常,因为IQueryProvider会把查询操作转为T-SQL,交由远端执行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/21938.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

气泡式水位计施工技术要求

1、气泡式水位计压力气管出气口应安装并固定在最低水位处&#xff0c;其压力气管也应固定&#xff0c;有条件的可用金属管或塑料管保护。气泡式水位计安装示意图见附图。 2、安装要求 1&#xff09;检查气泡式水位计气管外观有无破损及变形&#xff1b; 2&#xff09;旋开带有…

特征工程技巧—Bert

前段时间在参加比赛&#xff0c;发现有一些比赛上公开的代码&#xff0c;其中的数据预处理步骤值得我们参考。 平常我们见到的都是数据预处理&#xff0c;现在我们来讲一下特征工程跟数据预处理的区别。 数据预处理是指对原始数据进行清洗、转换、缩放等操作&#xff0c;以便为…

Blackwell未来发展之路究竟如何?

英伟达Blackwell如何重塑AI计算的未来&#xff1f; 前言 台湾大学演讲 就在6月2日&#xff0c;英伟达CEO黄仁勋在中国台湾大学综合体育馆发表了最新的演讲。这次黄仁勋的演讲依旧重磅&#xff0c;更值得注意的是这次演讲中还透露了Blackwell今后的发展之路。 介绍Blackwell 介绍…

MongoDB CRUD操作:地理位置查询

MongoDB CRUD操作&#xff1a;地理位置查询 文章目录 MongoDB CRUD操作&#xff1a;地理位置查询地理空间数据GeoJSON对象传统坐标对通过数组指定&#xff08;首选&#xff09;通过嵌入文档指定 地理空间索引2dsphere2d 地理空间查询地理空间查询运算符地理空间聚合阶段 地理空…

拿笔记下来!产品采购制造类合同怎样写比较稳妥?

拿笔记下来&#xff01;产品采购制造类合同怎样写比较稳妥&#xff1f; 近日&#xff0c;几经波折&#xff0c;泰中两国终于完成了潜艇采购谈判&#xff01;你知道吗&#xff1f;产品制造类合同或协议在起草前如果没有充分考虑各种因素&#xff0c;可能会导致一系列问题和不利…

C语言学习:数据类型

一、 为什么要引入数据类型 • 计算机中每个字节都有一个地址&#xff08;类似门牌号&#xff09; • CPU通过 地址 来访问这个字节的空间 0x20001103 1 0 0 1 0 0 1 1 0x20001102 1 1 1 0 1 1 1 0 0x20001101 1 1 1 1 0 1 0 1 0x20001100 0 …

无人监控视频输出卡顿状态

设计思路&#xff0c;如下&#xff1a; 1.通过采集卡将视频信号输出到个人PC中 2.PC按设置好的时间&#xff0c;视频属性分片保存 3.将步骤2中的视频&#xff0c;按预处理要求&#xff0c;得到待计算的视频片段 4.使用SSIM算法计算预处理后的视频&#xff0c;将计算得到的数据存…

聊天机器人的实践过程

一、语聊机器人 OpenAI 的爆火&#xff0c;到如今也才一年多的时间&#xff0c;然而在过去的一年中&#xff0c;生成式AI的落地场景几乎 80%都是 ChatBot 的形式&#xff0c;那么今天这篇文章我们就来聊一下&#xff0c;生成式AI和IM能擦出怎么样的火花&#xff1f;以及各种场…

p13idea的其他操作

1 导入模块 错误示范&#xff1a; 正确示范&#xff1a; 2 删除模块 必须用delete才能删除干净&#xff0c;用remove删了之后还要回到文件里面把它删除掉

有钱还系统源码 人人还众筹还钱模式还贷系统源码

盈利模式&#xff1a; 1.系统里直推400 2.间推得200 3.升级是隔代匹配200 4.漏单直接设置归系统 5.九级匹配不到直接归平台 有钱还平台新注册会员&#xff0c;即新入的负债者要分9次分别资助先来的11名负债者每人200元&#xff0c;这笔资助不是一次性给到对方&#xff0c…

Mybatis的一级缓存

缓存 MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。MyBatis 3 中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。 Mybatis和Hibernate一样&#xff0c;也有一级和二级缓存&#xff0c;同样默认开启的只有一级缓存&#xff0c;二级缓…

脑部磁共振成像肿瘤分割方法(MATLAB 2018)

近年脑肿瘤发病率呈上升趋势&#xff0c;约占全身肿瘤的5%&#xff0c;占儿童肿瘤的70%。CT、MRI等多种影像检查方法可用于检测脑肿瘤&#xff0c;其中MRI应用于脑肿瘤成像效果最佳。精准的脑肿瘤分割是病情诊断、手术规划及后期治疗的必备条件&#xff0c;既往研究者对脑部肿瘤…

Python知识点12---Python的I/O操作

提前说一点&#xff1a;如果你是专注于Python开发&#xff0c;那么本系列知识点只是带你入个门再详细的开发点就要去看其他资料了&#xff0c;而如果你和作者一样只是操作其他技术的Python API那就足够了。 Python的流(I/O)操作&#xff0c;最简单的其实就是输入和输出&#x…

工厂的精益生产如此重要

什么是工厂的精益生产 精益生产&#xff08;Lean Manufacturing&#xff09;是一种起源于20世纪50年代日本丰田汽车公司的生产管理哲学。它的核心理念是通过消除生产过程中的浪费&#xff0c;优化流程&#xff0c;提高效率&#xff0c;从而实现成本降低和质量提升。精益生产不仅…

VRTK4.0学习——(二)

手柄绑定以及显示 1.导入CameraRigs.UnityXRPluginFramework 和 CameraRigs.TrackedAlias 预设&#xff0c;将CameraRigs.UnityXRPluginFramework拖入CameraRigs.TrackedAlias的Elements中即可&#xff0c;运行软件后即可看到手柄了 注&#xff1a;如果无法看到手柄&#xff…

MySQL:MySQL执行一条SQL查询语句的执行过程

当多个客户端同时连接到MySQL,用SQL语句去增删改查数据,针对查询场景,MySQL要保证尽可能快地返回客户端结果。 了解了这些需求场景,我们可能会对MySQL进行如下设计: 其中,连接器管理客户端的连接,负责管理连接、认证鉴权等;查询缓存则是为了加速查询,命中则直接返回结…

系统介绍在线直线度测量仪的测量原理

测头的测量原理 蓝鹏光电测头采用的是CCD成像法测量&#xff0c;CCD成像法是指将被测物放置在物方远心光路系统中进行成像&#xff0c;并利用成像位置的CCD芯片接收成像信息进行尺寸测量的方法。该测量方法的优点主要有两个&#xff1a;一是成像边界清晰&#xff0c;光电信号可…

从墙的功能出发 -分析欧特克Revit和广联达数维的差别

欧特克&#xff08;Autodesk&#xff09;在三维建模软件领域的影响力是有目共睹的&#xff0c;它是行业的头部产商&#xff0c;拥有众多的高质量的三维设计软件&#xff0c;涵盖了建筑设计、机械设计与制造和电影文娱行业。Revit是其发布的建筑三维建模软件&#xff0c;也是BIM…

如何用个人电脑搭建一台本地服务器,并部署项目到服务器详细教程(Ubuntu镜像)

前言 VirtualBox虚拟机软件是一款强大、免费且开源的虚拟化工具&#xff0c;它允许用户在单一物理机器上同时运行多个操作系统。他对比VMware就是更轻量级的虚拟机软件&#xff0c;而且操作更简单。 下载地址&#xff1a;Download_Old_Builds_7_0 – Oracle VM VirtualBox …

SpringMVC日期格式处理 分页条件查询

实现日期格式处理 实现分页条件查询&#xff1a; 分页条件查询 和 查询所有 是两个不同的方法&#xff0c;使用同一个mapper的查询功能&#xff0c;但是两个不同的业务方法 ​​​​​​​