大家好,非常高兴能在博客园跟大家分享一下我有限的开发经历中的一些经验心得,首先是跟大家分享下我对Linq的一些理解,这个系列中的绝大部分内容都是我根据自己的理解原创的对一些问题的理解与阐述,所谓原创,就是希望大家在读的过程中如果发现什么不对的地方能及时指出,这对我本人也是一个很大的帮助与提高,还有一个就是非常欢迎大家转载这个系列的文章,但是希望转载的时候能注明出处,谢谢。
在写具体的内容前,首先分享下我本节的参考资料——MSDN.
http://msdn.microsoft.com/zh-cn/library/bb397676.aspx
http://msdn.microsoft.com/zh-cn/library/bb397906.aspx
http://msdn.microsoft.com/zh-cn/library/bb397933.aspx
http://msdn.microsoft.com/zh-cn/library/bb397896.aspx
首先讲点可能大家都知道的废话,linq是用来做什么的。
Linq直译过来就是语言集成查询 (LINQ), 是一组技术的名称。
Linq支持数据源:SQL 数据库、ADO.NET 数据集、XML 文档和流以及 .NET 集合中的数据。
MSDN上说过,所有 LINQ 查询操作都由以下三个不同的操作组成:
1.获取数据源。
2.创建查询。
3.执行查询。
我们首先分析第二步和第三步,创建查询和执行查询是2个分开的过程,所有的linq都是延后执行的。
再来看第一步,获取数据源,在linq中对本地数据源(.NET 集合,ADO.NET 数据集)和远程数据源(SQL 数据库,XML 文档和流)的处理是不同的,具体的不同会在后面的章节中讲到,今天暂且略过。
我们再明确一个问题,什么样的数据源可以被linq处理。ok,要明白这个问题,我们再来看看第三步——执行查询。linq是如何被执行的?我们先来看个例子:
DataClasses1DataContext dataContext = new DataClasses1DataContext();
string aa = "Wuhan";
var query = from item in dataContext.Customers
where item.City == aa && item.CustomerId == 1
select item;
foreach (Customer customer in query.ToArray())
{
Console.WriteLine("CustomerID:{0} City:{1}", customer.CustomerId, customer.City);
}
看到例子,相信大家都明白了,linq的查询在foreach的时候执行,那么,是不是只有当你写出foreach的时候linq才会被执行,没有写出foreach的话linq就一定不会执行,答案显然是否定的。如果你使用一些聚合函数,比如query.First(),query.Max(),linq也会被执行,但是,虽然这个时候你没有写foreach,但聚合函数的执行原理还是用了foreach.
这样就引出了能执行linq的数据源的一个必要条件——要能被foreach.那么,什么样的数据源能被foreach,实现了 IEnumerable这个接口的数据源。
当然,上面这么写只是从推导一个“必要条件”的角度来帮助大家理解和记忆为什么linq支持的数据源必须要实现IEnumerable这个接口,那是不是实现了IEnumerable这个接口就可以了呢,我们接着来分析这个问题。
MSDN上说:
通过使用 C# 3.0 中引入的声明性查询语法,介绍性 LINQ 文档中的多数查询都被编写为查询表达式。但是,.NET 公共语言运行库 (CLR) 本身并不具有查询语法的概念。因此,在编译时,查询表达式会转换为 CLR 确实了解的内容:方法调用。这些方法称为“标准查询运算符”,它们具有如下名称:Where、Select、GroupBy、Join、Max、Average 等。可以通过使用方法语法而非查询语法直接调用这些方法。
我们来看个msdn上的例子:
int[] numbers = { 5, 10, 8, 3, 6, 12};
//Method syntax:
IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);
ok,我们再来看看这些扩展方法是定义在哪的,又是扩展的哪个类的方法。
这些扩展方法定义在
程序集: System.Core(在 System.Core.dll 中)
命名空间: System.Linq
类:Enumerable
中,
提供一组用于查询实现 IEnumerable<T> 的对象的 static(在 Visual Basic 中为 Shared)方法。
ok,到此我们再来梳理一下知识,查询表达式在CLR上是通过扩展方法执行的,而扩展方法是实现 IEnumerable<T> 的对象的 static方法。
所以到此,我们算是完全明白了为什么linq的数据源实现IEnumerable这个接口是不够的,必须是实现了IEnumerable<T>接口的数据源。
(继承结构:public interface IEnumerable<T> : IEnumerable)。
并且如果大家要使用linq,就必须引入System.Linq这个命名空间,因为扩展方法是定义在这个命名空间中的Enumerable这个类中
请大家注意,我个人认为重要的不是记住我们最后推出的这个结论,而是明白这个推导的过程和弄清楚推导中用到的各个知识点,再利用这个推导过程把这些知识点联系起来。
最后给下一节开个引子:在.net中可以用linq的本地数据源实现的是IEnumerable<T>这个接口。而远程数据源实现的是IQueryable<T>这个接口。
(继承结构:public interface IQueryable<T> : IEnumerable<T>, IQueryable, IEnumerable)。
最后的最后,感谢蔡鹏同学对本人一直以来的帮助,希望大家能继续关注我的博客,同时也附上他的博客链接:
http://travelcai.cnblogs.com/