mysql linq 查询超时_LINQ延迟查询

LINQ定义了一系列的标准查询操作符,我们可以通过这些操作符使用查询语法或者方法语法对数据源进行查询,LINQ在定义查询语句后并不会立即查询数据源,而是通过foreach对返回结果进行遍历的时候才会查询数据源,这种技术即LINQ延迟查询,举例如下:

//延迟查询

int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0};int i = 0;var q = numbers.Where(x => { i++; return x > 2; });foreach (var v inq)

{

Console.WriteLine("v = {0}, i = {1}", v, i);

}

此段代码输出如下

a58736870a3d528d587ed6212c04a9bb.png

由此可见,程序在执行foreach循环的时候才进行查询,此时对程序稍作修改,将查询后的结果转换为List:

//延迟查询

int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0};int i = 0;var q = numbers.Where(x => { i++; return x > 2; }).ToList();foreach (var v inq)

{

Console.WriteLine("v = {0}, i = {1}", v, i);

}

执行结果

7e72deac8666be63afece753ab7b59ae.png

程序在执行ToList的时候已经进行了查询,所以返回i值全部为10。LINQ的延迟查询为何如此,让我们查看一下扩展方法Where的源码,该方法在System.Linq命名空间下的Enumerable静态类中(http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,577032c8811e20d3):

public static IEnumerable Where(this IEnumerable source, Funcpredicate) {if (source == null) throw Error.ArgumentNull("source");if (predicate == null) throw Error.ArgumentNull("predicate");if (source is Iterator) return ((Iterator)source).Where(predicate);if (source is TSource[]) return new WhereArrayIterator((TSource[])source, predicate);if (source is List) return new WhereListIterator((List)source, predicate);return new WhereEnumerableIterator(source, predicate);

}

也就是说定义var q = numbers.Where(x => { i++; return x > 2; });程序只是返回了一个WhereArrayIterator对象,该对象有一个指向源数据和lambda表达式的引用,该类源码如下:

class WhereArrayIterator : Iterator{

TSource[] source;

Funcpredicate;intindex;public WhereArrayIterator(TSource[] source, Funcpredicate) {this.source =source;this.predicate =predicate;

}public override IteratorClone() {return new WhereArrayIterator(source, predicate);

}public override boolMoveNext() {if (state == 1) {while (index

TSource item=source[index];

index++;if(predicate(item)) {

current=item;return true;

}

}

Dispose();

}return false;

}public override IEnumerable Select(Funcselector) {return new WhereSelectArrayIterator(source, predicate, selector);

}public override IEnumerable Where(Funcpredicate) {return new WhereArrayIterator(source, CombinePredicates(this.predicate, predicate));

}

}

我们看到MoveNext()方法下的if (predicate(item))语句,程序在此处对源数据的每一个值进行判定,所以当对返回的WhereArrayIterator对象进行foreach循环时,编译器会将foreach语句解析为下面形式的代码段,代码执行MoveNext时会同时进行查询。

IEnumerator enumerator =q.GetEnumerator();while(enumerator.MoveNext())

{

TSource p=enumerator.Current;

Console.WriteLine("v = {0}, i = {1}", p, i);

}

使用ToList方法为何会直接查询到所有结果,我们查看Enumerable类下的ToList扩展方法:

public static List ToList(this IEnumerablesource) {if (source == null) throw Error.ArgumentNull("source");return new List(source);

}

ToList方法返回一个新的List对象,我们再看List的构造函数

public List(IEnumerablecollection)

{if (collection==null)

ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);

Contract.EndContractBlock();

ICollection c = collection as ICollection;if( c != null) {int count =c.Count;if (count == 0)

{

_items=_emptyArray;

}else{

_items= newT[count];

c.CopyTo(_items,0);

_size=count;

}

}else{

_size= 0;

_items=_emptyArray;//This enumerable could be empty. Let Add allocate a new array, if needed.//Note it will also go to _defaultCapacity first, not 1, then 2, etc.

using(IEnumerator en =collection.GetEnumerator()) {while(en.MoveNext()) {

Add(en.Current);

}

}

}

}

构造函数将源数据转换为ICollection,因为我们的源数据类型无法转换为ICollection,则返回null,之后执行else段的代码,在此处执行en.MoveNext()进行查询数据源。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值