LINQ的执行时间
来源:互联网 发布:算法总结 编辑:程序博客网 时间:2024/06/05 17:30
LINQ的查询执行遵循以下原则:
1、一般情况下(除了下面第三条说的情况),LINQ都是延迟执行,原因:以DLINQ为例,越晚被执行,对业务逻辑的理解就越清晰,DLINQ查询对数据库的请求压力越小。编译器对LINQ查询优化可作的事情越多。
2、由于是延迟执行,也就是调用的时候才去执行。这样调用一次就被执行一次,这样就具备了重复执行的功能,参看之前的几个重复执行的例子。而这个重复执行是不需要再此书写一边查询语句的。
3、如果查询中我们对查询结果使用了 ToArray、ToList、ToDictionary 这些转换成集合的扩展方法。使用这时候出来的对象是一个独立的集合数组,而不是LINQ查询,所以这时候不会出现多次查询,而只是一次查询。
延迟执行 对于多数的查询操作符来说, 他们并不是在构造后被立即执行, 而是当枚举发生的时候, 换句话说就是当它对应的枚举器上的MoveNext被调用的时候. 例如下面的查询: 可以发现我们在查询构造之后插入的数字也包含在结果之中, 因为只有当foreach表达式运行的时候过滤或者排序才会发生. 我们把它称为延迟执行. 几乎所有的标准查询操作符都具有延迟执行的能力, 但以下这些是例外: 1. 那些返回单一元素或者单一值得操作符, 例如First或者Count 2. 转换操作符: ToArray, ToList, ToDictionary, ToLookup 这些操作符会被立即执行因为他们的返回类型没有任何的机制来提供延迟执行. 例如Count, 返回一个简单的整数类型, 没有办法被枚举. 例如下面的查询会被立即执行: 延迟执行非常重要是因为它将查询构造和执行解耦了. 这允许你可以分几步构造一个查询, 并使LINQ to SQL变得可能. 重估值 延迟执行还带来另外一个后果, 就是当你重新枚举的时候延迟执行的查询将会被重新计算. 有几个理由可以解释为什么重估有些时候会带来一些不利的影响: 1. 有些时候你想在一个特定的点及时冻结或者缓存结果 2. 有些查询是密集计算(或者依赖于一个远程数据库), 因此我们不想做一些不必要的重复. 要避免重估我们可以调用一个转换操作符, 例如ToArray或者ToList. ToArray将一个输出序列拷贝到一个数组, ToList则是将其拷贝到一个泛型的List<>: 外部变量 如果查询语句中的Lambda表达式引用了本地变量, 这些变量的值将是查询被执行时候的值, 而不是第一次被捕获时候的值, 例如: 当我们使用一个foreach循环创建一个查询的时候这可能会是一个陷阱, 例如: 延迟执行是如何工作的? 查询操作符通过返回装饰过的序列来提供延迟执行功能. 与传统的集合类( 例如Array或者Linked List)不同的是, 一个装饰过的序列本身并没有自己的数据结构来存储元素, 相反的, 它包装了你在运行时提供的序列, 因此, 它保持了一个永久的依赖. 任何时候你从装饰器中请求数据, 它都会将请求转发到包装过的输入序列中去. 调用Where操作符的时候只是构造了装饰序列, 并保持了输入序列, Lambda表达式和其他参数的引用. 只有当装饰器被枚举的时候输入序列才会被枚举. 例如: 当你枚举lessThanTen的时候, 你实际上是在通过where装饰器查询数组. 一个好消息是你可以通过一个C#迭代器来实现装饰序列从而编写你自己的查询操作符. 以下演示了怎么编写你自己的Select方法: 此方法是利用了yield return表达式的优点返回了一个迭代器, 以下是一个相同表达的快捷版本: 在这里, SelectSequence是一个有编译器生成的类型,其枚举器将逻辑装入迭代方法中.因此, 当你调用一个操作符例如Select或者Where的时候, 你实际上仅仅是实例化了一个包装了输入序列的可枚举类型, 仅此而已. 链式装饰器 连接多个查询操作符可以用来创建一个多层的装饰器. 考虑下面的查询: 每一个查询操作符实例化了一个新的装饰器,这个装饰器又包装了之前的序列. 当你枚举query的时候, 你是在查询最初的数组, 并让其穿过一个多层的链式装饰器来完成转换. 另外, 延迟执行的一个特性就是如果你使用渐进式的方式组建你的查询, 也可以创建一个完全等同的对象模型: 查询是怎么执行的? 这是枚举之前的查询得到的结果: foreach (int n in query) Console.Write (n + ","); // 30,50, 在幕后, foreach调用了Select装饰器上的GetEnumberator(最外面的操作符),然后开始触发所有的事件. 结果就是一个链式枚举器结构上对应到一个链式的装饰器序列. 一个查询就是一个生产线的传送带, 我们可以说一个LINQ查询就是一个懒惰的生产线, 传送带和lambda工人根据需求来生产各个元素. 构造一个查询就是在构造一个生产线 – 我们具备了所有的一切条件– 但还没有生产任何的东西. 当消费者请求一个元素的时候(枚举查询结果), 最右边的传送带激活, 然后触发其他的传送带开始生产 –这时需要提供一个输入序列. LINQ使用了一个需求驱动的拉模型, 而不是一个供应驱动的推模型. 这对于LINQ to SQL是非常重要的. 1: var numbers = new List<int>( );
2: numbers.Add (3);
3:
4: IEnumerable<int> q = numbers.Select (n => n + 2);
5: numbers.Add (5);
6:
7: foreach (int n in q)
8: Console.Write (n + ","); //5,7,
1: int result = numbers.Where (n => n <6).Count();
2: Console.WriteLine(result); //2
1: var numbers = new List<int>( ) { 5, 6 };
2:
3: IEnumerable<int> q = numbers.Select (n => n + 10);
4: foreach (int n in q)
5: Console.Write (n + ","); // 15,16,
6:
7: numbers.Clear( );
8: foreach (int n in q)
9: Console.Write (n + ","); // nothing
1: var numbers = new List<int>( ) { 5, 6, 7 };
2:
3: List<int> r = numbers
4: .Select (n => n + 10)
5: .ToList( );
6:
7: numbers.Clear( );
8: Console.WriteLine (r.Count); //3
1: int[] numbers = { 10, 20 };
2: int factor = 10;
3: var query = numbers.Select (n => n * factor);
4: factor = 20; // Change value
5: foreach (int n in query)
6: Console.Write (n + ","); // 200,400,
1: IEnumerable<char> query = "Not what you might expect";
2: foreach (char vowel in "aeiou")
3: {
4: char temp = vowel;
5: query = query.Where (c => c != temp); //如果使用vowel, 那么将只有’u’会被删除
6: }
1: IEnumerable<int> lessThanTen =
2: new int[] { 5, 12, 3 }.Where (n => n < 10);
1: static IEnumerable<TResult> Select<TSource,TResult> (
2: this IEnumerable<TSource> source,
3: Func<TSource,TResult> selector)
4: {
5: foreach (TSource element in source)
6: yield return selector (element);
7: }
1: static IEnumerable<TResult> Select<TSource,TResult> (
2: this IEnumerable<TSource> source,
3: Func<TSource,TResult> selector)
4: {
5: return new SelectSequence (source, selector);
6: }
1: IEnumerable<int> query = new int[] { 5, 12, 3 }
2: .Where (n => n < 10)
3: .OrderBy (n => n)
4: .Select (n => n * 10);
1: IEnumerable<int>
2: source = new int[] { 5, 12, 3 },
3: filtered = source .Where (n => n < 10),
4: sorted = filtered .OrderBy (n => n),
5: query = sorted .Select (n => n * 10);
- LINQ的执行时间
- 计算页面的执行时间
- sql 的执行时间
- javascript代码的执行时间?
- 代码的执行时间
- SQLSERVER语句的执行时间
- 获取执行时间的宏
- SQLSERVER语句的执行时间
- 程序执行时间的函数
- schedule的执行时间问题
- 多线程执行时间的差异
- Python执行时间的计算方法
- 测试Java代码的执行时间
- 查看SQL语句的执行时间
- 测量java代码的执行时间
- java里执行时间的比较!
- oracle自定义函数的执行时间
- 取得页面执行时间的代码
- 第三步 SQLDAL 放操作层 (操作类) Member(一)
- 第三步 SQLDAL 放操作层 (操作类) Member(二)
- 操作类的一些SQL 储存过程
- 第四步 WEB 展示层(显示层) UserReg.aspx 页 实例
- 第四步 WEB 展示层(显示层) UserReg.aspx.cs 页 实例
- LINQ的执行时间
- 数码管扫描程序(采用数据表格)
- 3G传输网络技术及建网策略
- OracleERP表结构-INV模块
- dfg
- QQ空间的几张图
- 深入体验JAVA Web开发内幕——核心基础
- 自增操作符(华为面试)
- 在.NET去掉文件的只读属性