理论的准备
查询是软件开发中的常见需求,其核心要素有三点:
- 获取数据源,包括且不限于线性表、映射、集合等数据结构、XML 文档、SQL 数据库等等
- 创建查询,设置查询条件
- 执行查询,得到查询结果
长期以来,开发人员对于他们必须支持的每种数据源或数据格式开发了各种各样的查询API,开发人员习惯性的将各种查询API的多样性,和API设计中可能存在的不一致性归结为数据源的多样性和不一致性。直到csharp语言创造性地将语言集成查询Linq(Language Integrated Query)直接集成到 C# 语言中,开发人员才惊奇地发现,原来如此常见的查询功能背后还隐藏着更为深刻的逻辑。
- 对于获取数据源,奥秘的关键就是数据源一致性,只要将数据源抽象为IEnumerable(或更通俗地理解为可数的)就可以屏蔽掉数据源的多样性,尽管这种抽象确实无法解决所有的数据源问题,但是也足够解决80%以上的问题了。
- 对于创建查询,设置查询条件,常用的SQL已经做出了很好的表率,SQL几乎可以解决所有关系型数据库的查询问题,它也是领域特定语言DSL(Domain Specific Language)的典型范例。原则上,SQL的设计更倾向于针对人类设计的,直接将SQL集成到倾向于针对机器设计的编程语言中,这确实是微软的一个大胆的设计。
- 对于执行查询,得到查询结果,这里可以进行优化的设计是引入惰性求值的概念,即延迟执行,尽可能的将复杂的查询延迟到最后才执行,这不仅能避免不必要的查询操作,而且也可以为查询的优化提供更全面的上下文。
理论的准备其实就是这些了,想不通时百思不得其解,想通了时也不过如此而已。
入门示例
直接来个直观的例子吧:
class HelloLINQ
{
static void Main()
{
// The Three Parts of a LINQ Query:
// 1. Data source.
int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
// 2. Query creation.
// numQuery is an IEnumerable<int>
var numQuery =
from num in numbers
where (num % 2) == 0
select num;
// 3. Query execution.
foreach (int num in numQuery)
{
Console.Write("{0,1} ", num);
}
}
}