走进Linq-Linq to SQL源代码赏析,通过Linq to SQL看Linq
[2] 走进Linq-Linq to SQL源代码赏析,通过Linq to SQL看Linq
[3] 走进Linq-Linq to SQL源代码赏析,通过Linq to SQL看Linq
系列文章导航:
不能不说的C#特性-迭代器(下),yield以及流的延迟计算
走进Linq-Linq to SQL How do I(1)
走进Linq-Linq to SQL How do I(2)
走进Linq-Linq to SQL How do I(3)
走进Linq-Linq to SQL源代码赏析 Table
走进Linq-Linq to SQL源代码赏析之Provider的初始化
走进Linq-Linq to SQL源代码赏析,通过Linq to SQL看Linq
既然如此那我们就得看看Table<TEntity>的GetEnumerator方法了:
{
return ((IEnumerable<TEntity>)this.context.Provider.Execute(Expression.Constant(this)).ReturnValue).GetEnumerator();
}
从这里可以看出它是通过调用IProvider的Execute方法。
关于Execute更深层次的内容,在本篇中并不涉及,你只要知道它根据Lambda表达式生成SQL语句,然后对数据库进行操作就OK了。
如果存在这样一个查询:
Var result = posts.Where(p=>p.id==1);
这样的一个查询到底会发生什么呢?实际上我们根本无从得知,如果posts是一个内存中的集合那么就是在内存中进行对象的筛选,实际上就是执行一下一个foreach,然后将符合p.Id == 1这个条件的所有Post对象都添加到返回的集合中;如果posts是一个Table<TEntity>对象,那么这个查询最后将生成SQL语句对数据库进行操作。一样是Where,传入的参数也是Lambda表达式,为什么产生的结果却不同呢?两个Where真的是相同的么?
实际上在我们对内存中的集合使用Where等扩展方法的时候是使用Enumerable类对IEnumerable<T>的扩展。
我们再来看看Table<TEntity>,它实现了IQueryable<T>接口,IQueryable<T>有一个IQueryProvider类型的成员。在System.Linq命名空间下还有一个Queryable类,这个类是对IQueryable<T>接口进行扩展的。那现在看来Linq to SQL和Linq to Objects并没有什么直接关系,唯一的就是靠IEnumerable<T>这个建立起桥梁,让它们查询的方式语言都统一。
我们再来看看Enumerable和Queryable中的扩展方法有什么不同:
Enumerable中的扩展方法接受的一般都是委托类型的参数,而Queryable中接受的却是Expression,但为什么它们都可以接受Lambda表达式作为参数呢?
神奇的赋值符号“=”
Func<int,bool> IsTrue = x=>x==5;
Expresssion<Func<int,bool>> IsTrue = x =>x==5;