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 ...
随机推荐
- 用Qemu模拟vexpress-a9 (四) --- u-boot引导kernel,用nfs挂载根文件系统
环境介绍 Win7 64 + Vmware 11 + ubuntu14.04 32 u-boot 版本:u-boot-2015-04 Linux kernel版本:linux-3.16.y busyb ...
- 按照索引的细化提取骨架算法的java实现
近期研究验证码识别,也就看了一些图像识别的资料,其中一种字体细化提取骨架的算法网上没有java版的实现,所以就选取了一个python实现版本进行java代码的改写.. python版实现的地址: ht ...
- SSIS ETL BEST PRACTICE
PackageRunLog(ExecutionGuid,PackageName,SourceTableName,DestinationTableName,StartTimeUTC,EndTimeUTC ...
- 这一路走来,冷暖自知 (附算法demos)
最近半年多,除了“一键修图”算法之外我还做了其他什么算法? 1.实时单图HDR算法(颜色矫正,智能曝光) 2.多图曝光融合HDR算法(最高支持八百万像素左右) 3.模拟热能探测算法 4.防伪探测算法 ...
- UESTC 32 树上战争(Battle on the tree)
这题其实很简单,每个人肯定都往上走,才能保证尽快赢,所以无非是看谁离根节点近,即深度小..用并查集中的findset思想,不断找父节点一直到根节点来找深度就可以了. 代码: #include < ...
- fastDFS 一二事 - 简易服务器搭建(单linux)
什么是FastDFS FastDFS是一个叫余庆的哥们用c语言编写的一款开源的分布式文件系统 功能有冗余备份.负载均衡.线性扩容等,高可用.高性能 可以用FastDFS搭建一套高性能的文件服务器集群提 ...
- VA助手(Visual Assist X) 笔记
官方网站:http://www.wholetomato.com/ 一. 快捷键 Shift+Alt+F Find References 查找引用 Shift+Alt+S FindSynbolDialo ...
- SqlServer 注入技巧
一.SA权限执行命令,如何更快捷的获取结果? 有显示位 显示位 其实这里的关键并不是有无显示位.exec master..xp_cmdshell 'systeminfo'生成的数据写进一张表的时候,会 ...
- 颗粒翻页(css3效果展示)
用css3效果做了一个颗粒翻页效果,布局上,一张图片做底层,在这张图片上用js创建一层小的行和列各为r和c的小span,给这些span分别设置background-position:用来覆盖原来的一张 ...
- css3新属性的总结
今天继续总结css3的一些css3新样式,先列一个简单的提纲,重要的还是圆角.阴影.渐变.文字缩略,最最重要的是过度transition,变换transform和animation圆角阴影渐变 圆形渐 ...