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 ...
随机推荐
- maven添加远程私服
文件放在maven下和..m2下面 <?xml version="1.0" encoding="UTF-8"?> <!-- License ...
- Linux Strip
一.简介 strip经常用来去除目标文件中的一些符号表.调试符号表信息,以减小程序的大小. 二.语法 https://sourceware.org/binutils/docs/binutils/str ...
- LinuxI2C核心、总线驱动与设备驱动
I2C体系结构分为三个部分:I2C核心.总线驱动.设备驱动 I2C核心: I2C核心提供了一组不依赖硬件的接口函数,I2C总线驱动和设备驱动之间依赖于I2C核心作为纽带 (1)增加/删除i2c_ada ...
- 利用Google Speech API实现Speech To Text
很久很久以前, 网上流传着一个免费的,识别率暴高的,稳定的 Speech To Text API, 那就是Google Speech API. 但是最近再使用的时候,总是返回500 Error. 后来 ...
- UVALive 5966 Blade and Sword -- 搜索(中等题)
题意:给一幅地图,P为起点,D为终点,'*'为传送阵,到达传送阵可以传到任意一个其他的传送阵,传到以后可以正常走或者再传回来,问P->D最短步数. 分析:这题一定要细心,分析要到位才能搞定,错一 ...
- 【shiro】shiro学习笔记1 - 初识shiro
[TOC] 认证流程 st=>start: Start e=>end: End op1=>operation: 构造SecurityManager环境 op2=>operati ...
- win10自动更新彻底关闭
http://app.techweb.com.cn/wp/2016-10-24/2418646.shtml
- finder怎么才能找到library
右键Finder——前往目录 输入~/Library
- msg url
- 16SpringMvc_在业务控制方法中写入User,Admin多个模型收集参数——引出问题
上面文章时普通的业务那个方法中收集一个实体类,这篇文章想收集两个实体类. 文本要做的是:在person.jsp页面上,有两个表单.分别是普通用户和管理员用户的表单(普通用户的表单和管理员用户的表单里面 ...