LINQ之延迟加载及其原理
这是LINQ(集成化查询)的继续及补充,在前面我已经介绍过,在LINQ中,一个重要的特性就是延迟加载,是指查询操作并不是在查询运算符定义的时候执行,而是在真正使用集合中的数据时才执行(如:在遍历集合时调用MoveNext方法时)。下面是一个简单的实例:
var num = new List<int>();
num.Add();
IEnumerable<int> query = num.Select(n => n * );
num.Add();
foreach (int n in query)
Console.WriteLine(n);
结果输出10 20.在上面的例子中,在创建查询语句后又向集合中加入新元素,这个新元素最终也出现在查询结果中。这就是因为查询语句是在遇到foreach之后才真正执行的,再例如:
Action a = () => Console.WriteLine("Foo");
//没有在控制台输出任何内容
a();
//延迟执行,输出Foo
绝大部分标准的LINQ查询运算符都具有延迟加载这种特性,但也有例外:
- 那些返回单个元素或返回一个数值的运算符,如First或Count。
- 转换运算符:ToArray,ToList,ToDictonnary,ToLookup。
以上这些运算符都会触发LINQ语句立即执行,因为它们的返回值类型不支持延迟加载。
延迟加载的工作原理
LINQ查询运算符之所以有延迟加载功能,是因为每个返回值不是一般的数组或集合,而是一个经过封装的序列,这种序列通常情况下并不直接储存数据元素,它封装并使用运行时传递给它的集合,元素也由其他集合来储存,它实际上只是维护自己与数据集合的一种依赖关系,当有查询请求时,再到它以来的序列中进行真正的查询。查询运算符实际上是封装一系列的转换函数,这种转换函数可以将与之关联的数据转换为各种形式的序列。如果输出集合不需要转换的话,那么就不用执行查询运算符封装的转换操作,这个时候查询运算符实际上就是一个委托,进行数据转发而已。
例如调用Where运算符的时候,在Where内部所做的操作非常简单,根据Lambda表达式中指定的查询条件,对输入集合重新进行了筛选,保留那些符合条件的元素指针引用,当外部遍历Where的返回值时,Where回到它所关联的集合中进行真正的查询,然后返回查询结果。
IEnumerable<int> lessThanTen = new int[] { , , }.Where(n => n < );
当执行lessThanTen操作时,实际上,就是使用where运算符对封装序列进行筛选。
当需要使用一些有特殊功能的运算符时,我们可以自定义实现。例如下面这个实例所示,实现一个自定义的Select运算符:
public static IEnumerable<TResult> Select<TSource,TResult>(
this IEnumerable<TSource> source,Func<TSource,TResult> selector)
{
foreach (TSource element in source)
yield return selector(element);
}
上面这个方法实际上就是在循环中返回yield类型的元素。所以当调用Select和Where查询运算符时,内部操作就是创建一个序列,然后将查询得到的元素存入这个新的序列中。
其实,在LINQ中,延迟加载特性是很重要的,这种设计将查询的转换和查询的执行进行了解耦,这使得我们可以将查询分成多个步骤来创建,有利于查询表达式的书写,而且在执行的时候按照一个完整的结构去查询,减少了对集合的查询次数,这种特性对数据库查询尤其重要。
LINQ之延迟加载及其原理的更多相关文章
- Linq之延迟加载特性
目录 写在前面 系列文章 延迟加载 总结 写在前面 上篇文章介绍了linq中常见的几个关键字,并列举了几个例子,算是对linq如何使用有了初步了解.上篇文章中也提到了,能够使用linq的场合有一个要求 ...
- Linq、延迟加载、直接加载
1.集合常用扩展方法 Where.Max.Min.OrderBy. Select.//投影后的IEnumerable对象可以通过,AsQueryable转换数据类型 First.FirstOrDefa ...
- Linq的延迟加载问题
什么是延迟加载:所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作.可以简单理解为,只有在使用的时候,才会发出sql语句进行查询,数据是分N次读取. 什么是立即加载:所谓立即加载既是所有的 ...
- 转载有个小孩跟我说LINQ(重点讲述Linq中GroupBy的原理及用法)
转载原出处: http://www.cnblogs.com/AaronYang/archive/2013/04/02/2994635.html 小孩LINQ系列导航:(一)(二)(三)(四)(五)(六 ...
- linq之延迟加载和即时加载+标准查询运算符
延迟加载 Linq查询的执行结果是IEnumerable<T>类型,而对IEnumerable<T>,在内部,C#通过yield关键字实现迭代器达到延迟加载的目的.从而使Lin ...
- 图片延时加载原理 和 使用jquery实现的一个图片延迟加载插件(含图片延迟加载原理)
图片加载技术分为:图片预加载和图片延时加载. javascript图片预加载和延时加载的区别主要体现在图片传输到客户端的时机上,都是为了提升用户体验的,延时加载又叫懒加载.两种技术的本质:两者的行为是 ...
- Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?
Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association 指的就是一对一,collection 指的就是一对多查询.在 Myba ...
- 使用NHibernate(8)-- 延迟加载
1,延迟加载. 延迟加载,即用到的时候再加载数据.这种机制是非常有情怀的,比如一篇中的用户实体有标签.问题等导航属性,如果只是用到用户名去查询整个实体,则把相关的标签和问题也都加载,性能会比较低.而有 ...
- (第一篇) 一步一步带你了解linq to Object
要想学好linq to object 我们必须要先学习lambda 表达式,学习lambda 表达式呢我们必须了解匿名函数和匿名类及扩展方法,学习匿名函数,我们必须学会委托,这是本文的宗旨.下面开始第 ...
随机推荐
- 四核驱动的三维导航—淘宝新UI(设计篇)
前面有一篇博客说到了淘宝UWP的"四核驱动的三维导航—淘宝新UI(需求分析篇)",花了两周的时间实现了这个框架,然后又陆陆续续用了三周的时间完善它. 多窗口导航,与传统的导航方式的 ...
- WPF+通过配置文件生成菜单(Menu)+源码
这个月做项目,遇到过一个通过配置文件来生成菜单的解决方案,感觉挺优雅的,特地放到博客园来,以飨读者. 说来惭愧,以前做的项目都没有这样用过,都是固定死了.如果后续有需要加入菜单,还得在重新修改UI,然 ...
- 在MotionBuilder中绑定C3D动作和模型
[题外话] 实验室人手不足,虽然自己连MotionBuilder一点都没有用过,但是老板叫自己干也只能硬着头皮上了.本文详细介绍了MotionBuilder 2013中的摄像机操作以及在MotionB ...
- 辛巴学院-Unity-剑英陪你零基础学c#系列(四)函数和封装
辛巴学院:正大光明的不务正业. 国庆长假结束了,我的心情是这样的: 你总是起不早,起不早独自一个人沉睡到天亮你无怨无悔的梦着那副本我知道你根本就不想上班你总是起不早,起不早放假总是短暂,上班太难请个病 ...
- [备忘]检索 COM 类工厂中 CLSID 为 {91493441-5A91-11CF-8700-00AA0060263B} 的组件时失败解决方法
检索 COM 类工厂中 CLSID 为 {91493441-5A91-11CF-8700-00AA0060263B} 的组件时失败,原因是出现以下错误: 80070005 在CSDN上总是有网友问这个 ...
- 混合 Data Warehouse 和 Big Data 倉庫的新架構
(讀書筆記)許多公司,儘管想導入 Big Data,仍必須繼續用 Data Warehouse 來管理結構化的營運數據.系統記錄.而 Big Data 的出現,為 Data Warehouse 提供了 ...
- netstat
netstat再解读 C:\Users\Administrator>netstat -nb 活动连接 协议 本地地址 外部地址 状态 TCP ESTABLISHED [mysqld.exe] T ...
- MongoDB 安装和可视化工具
MongoDB 是一款非常热门的NoSQL,面向文档的数据库管理系统,官方下载地址是:MongoDB,博主选择的是 Enterprise Server (MongoDB 3.2.9)版本,安装在Win ...
- HTML5系列:HTML5绘图
1. canvas元素基础 canvas元素是HTML5中新增的一个重要元素,专门用来绘制图形. 在页面中使用canvas元素绘制图形需要经过的三个步骤: 步骤一 使用canvas元素创建一个画布区 ...
- 操作系统页面置换算法(opt,lru,fifo,clock)实现
选择调出页面的算法就称为页面置换算法.好的页面置换算法应有较低的页面更换频率,也就是说,应将以后不会再访问或者以后较长时间内不会再访问的页面先调出. 常见的置换算法有以下四种(以下来自操作系统课本). ...