这是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之延迟加载及其原理的更多相关文章

  1. Linq之延迟加载特性

    目录 写在前面 系列文章 延迟加载 总结 写在前面 上篇文章介绍了linq中常见的几个关键字,并列举了几个例子,算是对linq如何使用有了初步了解.上篇文章中也提到了,能够使用linq的场合有一个要求 ...

  2. Linq、延迟加载、直接加载

    1.集合常用扩展方法 Where.Max.Min.OrderBy. Select.//投影后的IEnumerable对象可以通过,AsQueryable转换数据类型 First.FirstOrDefa ...

  3. Linq的延迟加载问题

    什么是延迟加载:所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作.可以简单理解为,只有在使用的时候,才会发出sql语句进行查询,数据是分N次读取. 什么是立即加载:所谓立即加载既是所有的 ...

  4. 转载有个小孩跟我说LINQ(重点讲述Linq中GroupBy的原理及用法)

    转载原出处: http://www.cnblogs.com/AaronYang/archive/2013/04/02/2994635.html 小孩LINQ系列导航:(一)(二)(三)(四)(五)(六 ...

  5. linq之延迟加载和即时加载+标准查询运算符

    延迟加载 Linq查询的执行结果是IEnumerable<T>类型,而对IEnumerable<T>,在内部,C#通过yield关键字实现迭代器达到延迟加载的目的.从而使Lin ...

  6. 图片延时加载原理 和 使用jquery实现的一个图片延迟加载插件(含图片延迟加载原理)

    图片加载技术分为:图片预加载和图片延时加载. javascript图片预加载和延时加载的区别主要体现在图片传输到客户端的时机上,都是为了提升用户体验的,延时加载又叫懒加载.两种技术的本质:两者的行为是 ...

  7. Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?

    Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association 指的就是一对一,collection 指的就是一对多查询.在 Myba ...

  8. 使用NHibernate(8)-- 延迟加载

    1,延迟加载. 延迟加载,即用到的时候再加载数据.这种机制是非常有情怀的,比如一篇中的用户实体有标签.问题等导航属性,如果只是用到用户名去查询整个实体,则把相关的标签和问题也都加载,性能会比较低.而有 ...

  9. (第一篇) 一步一步带你了解linq to Object

    要想学好linq to object 我们必须要先学习lambda 表达式,学习lambda 表达式呢我们必须了解匿名函数和匿名类及扩展方法,学习匿名函数,我们必须学会委托,这是本文的宗旨.下面开始第 ...

随机推荐

  1. 编译可在Nexus5上运行的CyanogenMod13.0 ROM(基于Android6.0)

    编译可在Nexus5上运行的CyanogenMod13.0 ROM (基于Android6.0) 作者:寻禹@阿里聚安全 前言 下文中无特殊说明时CM代表CyanogenMod的缩写. 下文中说的“设 ...

  2. 玩转Windows服务系列——命令行管理Windows服务

    说到Windows服务的管理就不得不说通过命令行的方式管理Windows服务,因为无论是系统管理员,还是通过编程的方式调用cmd命令,命令行都是非常方便以及强大的工具. 接下来就看一下如何通过cmd命 ...

  3. SQL Server 2012 Managed Service Account

    原创地址:http://www.cnblogs.com/jfzhu/p/4007472.html 转载请注明出处 (一)Windows服务使用的登陆帐号 Windows服务只有登录到某一帐户的情况下才 ...

  4. hibernate学习笔记之三 持久化的三种状态

    Hibernate持久化对象有3中状态,瞬时对象(transientObjects),持久化对象(persistentObjects),离线对象(detachedObjects) 下图显示持久化三种状 ...

  5. ElasticSearch ik分词安装

    1.下载对应版本的ES ik分词 https://github.com/medcl/elasticsearch-analysis-ik/releases 2.解压elasticsearch-analy ...

  6. Distributed1:Linked Server 添加和删除

    A linked server allows for access to distributed, heterogeneous queries against OLE DB data sources. ...

  7. SSIS Execute SQL Task 用法

    Execute Sql Task组件是一个非常有用的Control Flow Task,可以直接执行SQL语句,例如,可以执行数据更新命令(update,delete,insert),也可以执行sel ...

  8. 学用MVC4做网站六后台管理:6.1.1管理员登录、6.1.2退出

    1.管理员登录 在6.1中已添加控制器[AdministratorController] 在控制器中添加[Login()]action,用来显示登录页面 /// <summary> /// ...

  9. 使H1 H2等标签不换行

    在网页优化中,经常要使用H标签对关键字进行优化, 可是如果是一行文字中的某个词加上了H1标记,就会换行. 可以使用下面的方法,H标签就不会强制换行了. <style type="tex ...

  10. java中Set,Map,Stack一些简单用法

    import java.util.Iterator; import java.util.Stack; import java.io.*; import java.util.Set; import ja ...