Linq之延迟加载特性
目录
写在前面
上篇文章介绍了linq中常见的几个关键字,并列举了几个例子,算是对linq如何使用有了初步了解。上篇文章中也提到了,能够使用linq的场合有一个要求:实现IEnumerable<T>泛型接口,或者类型兼容(可以通过Cast方法转换,比如ArrayList)。
系列文章
延迟加载
延迟加载在很多orm框架中都有支持,什么是延迟加载?通俗一点,就是你需要的时候再去查询,不需要的时候就不查询。
Linq查询的执行结果是IEnumerable<T>类型,而对IEnumerable<T>,在内部,C#通过yield关键字实现迭代器达到延迟加载的目的。从而使Linq查询只是在需要的时候才会被执行。
下面看一个例子
namespace Wolfy.LinqLazyLoad
{
class Program
{
static void Main(string[] args)
{
List<Person> persons = new List<Person>() {
new Person(){ ID=,Name="wolfy1", Age=},
new Person(){ ID=,Name="wolfy2", Age=},
new Person(){ ID=,Name="wolfy3", Age=},
new Person(){ ID=,Name="wolfy4", Age=},
new Person(){ ID=,Name="wolfy5", Age=},
new Person(){ ID=,Name="wolfy6", Age=}
};
//这里使用linq进行查询
var query = from p in persons
.OrderByDescending(p => p.Age)
select new { p.ID, p.Name, p.Age };
//如果是linq是延迟加载的,则输出的结果就应该是修改后的(延迟加载,说明query中此时并没有实际加载数据)
//如果linq立即加载的,则此时query中就相当于一个临时的缓冲区,数据已经存在了query中,就算对persons中某一项修改并不影响query中的数据。
persons[] = new Person() { ID = , Name = "zhangsan", Age = };
foreach (var item in query)
{
Console.WriteLine(item.ToString());
}
Console.Read();
}
}
class Person
{
public int ID { set; get; }
public string Name { set; get; }
public int Age { set; get; }
public override string ToString()
{
return ID + " " + Name + " " + Age;
}
}
}
例子很简单,通过linq查询,按年龄降序输出。
看一下输出结果

通过这点也许你可能还不是很清楚。
那么我们再举一个linq立即加载的例子,对比一下
static void Main(string[] args)
{
List<Person> persons = new List<Person>() {
new Person(){ ID=,Name="wolfy1", Age=},
new Person(){ ID=,Name="wolfy2", Age=},
new Person(){ ID=,Name="wolfy3", Age=},
new Person(){ ID=,Name="wolfy4", Age=},
new Person(){ ID=,Name="wolfy5", Age=},
new Person(){ ID=,Name="wolfy6", Age=}
};
//使用聚合函数年龄总和
var result = (from p in persons
select p.Age)
.Sum();
//如果是linq是延迟加载的,则输出的结果就应该是修改后的(延迟加载,说明query中此时并没有实际加载数据)
//如果linq立即加载的,则此时query中就相当于一个临时的缓冲区,数据已经存在了query中,就算对persons中某一项修改并不影响query中的数据。
persons[] = new Person() { ID = , Name = "zhangsan", Age = };
Console.WriteLine("Sum " + result);
Console.Read();
}
输出结果

21=1+2+3+4+5+6。这里也说明一个问题,在linq中,一些聚合函数例如Sum,求平均值等操作会影响linq的延迟加载特性。
上面的第一个例子是延迟加载,在query中并没有加载数据,然后你修改了persons[2]的值,你再输出query中的每一个值的时候,此时才是真正的加载数据,而此时加载数据,persons[2]的值已经发生变化了,所以会输出最新的persons[2]。
第二个例子中,聚合函数为什么会影响延迟加载特性呢,其实也很好理解,比如在该例子中进行求和运算,求和运算就需要所有的值,所以就需要先将值查询出来,然后才能求和,此时已经将结果保存在了result中,就算你下面再修改persons[2]的值,也没有用了。
总结
通过上面的例子,以及Linq查询的执行结果是IEnumerable<T>类型,而对IEnumerable<T>,在内部,C#通过yield关键字实现迭代器达到延迟加载的目的。从而使Linq查询只是在需要的时候才会被执行,可以得到这样的结论:
1、可以自定义一个类实现泛型接口IEnumerable<T>,在迭代器块中通过yield关键字,可以实现延迟加载的目的。
2、linq中使用聚合函数,将会强制查询,将强制进行立即加载。
上面的例子,有点绕,各种缘由,需慢慢体会。
思考:为什么yield关键字就能实现延迟加载的特性呢?(查找很多资料,未果)
参考文章
http://kb.cnblogs.com/page/100043/
Linq之延迟加载特性的更多相关文章
- LINQ之延迟加载及其原理
这是LINQ(集成化查询)的继续及补充,在前面我已经介绍过,在LINQ中,一个重要的特性就是延迟加载,是指查询操作并不是在查询运算符定义的时候执行,而是在真正使用集合中的数据时才执行(如:在遍历集合时 ...
- Linq的延迟加载问题
什么是延迟加载:所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作.可以简单理解为,只有在使用的时候,才会发出sql语句进行查询,数据是分N次读取. 什么是立即加载:所谓立即加载既是所有的 ...
- Linq、延迟加载、直接加载
1.集合常用扩展方法 Where.Max.Min.OrderBy. Select.//投影后的IEnumerable对象可以通过,AsQueryable转换数据类型 First.FirstOrDefa ...
- linq之延迟加载和即时加载+标准查询运算符
延迟加载 Linq查询的执行结果是IEnumerable<T>类型,而对IEnumerable<T>,在内部,C#通过yield关键字实现迭代器达到延迟加载的目的.从而使Lin ...
- Linq学习笔记(转)
开始Linq前你要知道的 扩展方法 顾名思义就是对现有类进行扩展的的方法,扩展方法可以在不修改现有类的情况下,为现有类增加公共的接口(不是C#中的interface). 扩展方法本质上是一个静态方法, ...
- linq入门系列导航
写在前面 为什么突然想起来学学linq呢?还是源于在跟一个同事聊天的时候,说到他们正在弄得一个项目,在里面用到了linq to sql.突然想到距上次使用linq to sql是三年前的事情了.下班回 ...
- Linq之Linq to Sql
目录 写在前面 系列文章 Linq to sql 总结 写在前面 上篇文章介绍了linq to xml的相关内容,linq to xml提供一种更便捷的创建xml树,及查询的途径.这篇文章将继续介绍l ...
- Linq之Linq to XML
目录 写在前面 系列文章 linq to xml 总结 写在前面 在很多情况下,都可以见到使用xml的影子.例如,在 Web 上,在配置文件.Microsoft Office Word 文件(将wor ...
- Linq之Linq to Objects
目录 写在前面 系列文章 linq to objects 总结 写在前面 上篇文章介绍了linq的延迟加载特性的相关内容,从这篇文章开始将陆续介绍linq to Objects,linq to xml ...
随机推荐
- php 利用activeMq+stomp实现消息队列
php 利用activeMq+stomp实现消息队列 一.activeMq概述 ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J ...
- 【转载】chromium浏览器开发系列第一篇:如何获取最新chromium源码
背景: 最近摊上一个事儿,领导非要让写一篇技术文章,思来想去,自己接触chrome浏览器时间也不短了,干脆就总结一下吧.于是乎,本文顺理成章.由于有些细节必需描述清楚,所以这次先讲如何拿到ch ...
- windows内核编程之常用数据结构
1.返回状态 绝大部分的内核api返回值都是一个返回状态,也就是一个错误代码.这个类型为NTSTATUS.我们自己写的函数也大部分这样做. NTSTATUS MyFunction() { NTSTAT ...
- c# 参数传递
c#类型有值类型与引用类型. 无论哪种类型的变量,作为方法的参数进行传递时,默认是以"值传递"方式来传递的. 传递给方法的形参,在执行时都会新创建一个局部变量,然后接受实参的值, ...
- 免费微信公众号专用h5在线电影票API
免费h5在线电影票API,通过嵌套返回的h5页面url,实现电影票购买. 接口文档:https://www.juhe.cn/docs/api/id/252,通过此申请APPKEY 接口备注:通过请求返 ...
- [转]Excel - How to lock cell without using macros if possible
本文转自:http://stackoverflow.com/questions/11953214/excel-how-to-lock-cell-without-using-macros-if-poss ...
- ehcache 一二事 - ssm 中ehcashe的简单配置应用
Ehcache是一个开源Java分布式缓存.可以配合mybatis来使用 首先,在资源文件夹中新建ehcache.xml 内容如下: <?xml version="1.0&qu ...
- MongoDB学习(五)Linux环境安装MongoDB
一. 下载 从http://www.mongodb.org/downloads地址中下载:mongodb-linux-x86_64-2.4.11.tar 二. 安装 1>设置mongoDB ...
- IDEA 滚动条跳动问题
关掉有道词典的 “屏幕取词” 和 “划词翻译”
- ArcGis实现添加MultiLayerMarkerSymbol(多个符号叠加生成新的符号)
, , ); pMarkerSymbol.Angle = ; pMarkerSymbol.XOffset = ;;;;, , ); ...