第9章 LINQ查询基础

LINQ(Language Integrated Query,语言级集成查询)是Visual Studio 2008和.NET Framework 3.5版中才开始引入的一组.NET Framework扩展模块集合,它内含语言集成查询、集合以及转换操作,从而在对象领域和数据领域之间架起了一座桥梁。

传统上,针对数据的查询都是以简单的字符串表示,而没有编译时类型检查或IntelliSense支持。此外,还必须针对以下各种数据源学习一种不同的查询语言:SQL数据库、XML文档、各种Web服务等。LINQ使查询成为C#和Visual Basic中的一流语言构造,可以使用语言关键字和熟悉的运算符针对强类型化对象集合编写查询。

在Visual Studio中,可以很方便地使用C#和Visual Basic为以下数据源编写LINQ查询:SQL Server数据库、XML文档、ADO.NET数据集,以及支持IEnumerable或泛型IEnumerable<T>接口的任意对象集合。此外,还计划了对ADO.NET Entity Framework的LINQ支持,并且第三方为许多Web服务和其他数据库实现编写了LINQ提供程序。

9.1 LINQ查询概述

简单地讲,LINQ包括五个部分的内容,如图9-1所示。

❑LINQ to Objects:指直接对任意IEnumerable或IEnumerable<T>集合使用LINQ查询,无须使用中间LINQ提供程序或API,如LINQ to SQL或LINQ to XML。可以使用LINQ来查询任何可枚举的集合,如List<T>、Array或Dictionary<TKey, TValue>。该集合可以是用户定义的集合,也可以是.NET Framework API返回的集合。

❑LINQ to DataSet:它将LINQ和ADO.NET集成,它通过ADO.NET获取数据,然后通过LINQ进行数据查询,从而实现对数据集进行非常复杂的查询。可以简单把它理解成通过LINQ对DataSet中保存的数据进行查询。

❑LINQ to SQL:它是基于关系数据的.NET语言集成查询,用于以对象形式管理关系数据,并提供了丰富的查询功能。其建立于公共语言类型系统中的基于SQL的模式定义的集成之上,当保持关系型模型表达能力和对底层存储的直接查询评测的性能时,这个集成在关系型数据之上提供强类型。

❑LINQ to Entities:它使开发人员能够通过使用LINQ表达式和LINQ标准查询运算符,直接从开发环境中针对实体框架对象上下文创建灵活的强类型查询。

❑LINQ to XML:在System.Xml.LINQ命名空间下实现对XML的操作。采用高效、易用、内存中的XML工具在宿主编程语言中提供XPath/XQuery功能等。

figure_0343_0247

图 9-1 LINQ架构

下面将通过两个实际的例子演示如何使用LINQ来查询数组与SQL Server数据库,以便对LINQ查询有一个大致的了解。

9.1.1 查询数组

在日常的开发中,经常需要对数组中的数据做一些“筛选”操作。如下面的数组所示:


int[]num={1,2,3,4,5,6,7,8,9};


对于num数组,如需要从中“筛选”出大于5的数据并将结果显示出来。而在传统的开发过程中,如果要筛选其中大于5的数据,则需要遍历整个数组进行对比。如下面的代码所示:


//遍历数组

for(int i=0;i<num.Length;i++)

{

//判断数组元素的值是否大于5

if(num[i]>5)

{

//输出对象

Label1.Text+=num[i].ToString();

}

}


上述代码非常简单,将数组从头开始遍历,遍历中将数组中的值与5相比较,如果大于5就会输出该值,如果小于5就不会输出该值。虽然上述代码实现了功能的要求,但是这样编写的代码繁冗复杂,也不具有扩展性,并且还需要进行复杂的数组遍历。如果使用LINQ查询语句进行查询就非常简单。示例代码如下所示:


//执行LINQ查询语句

var result=from data in num where data>5 select data;

//遍历集合元素

foreach(variin result)

{

//输出对象

Label1.Text+=i.ToString();

}


这样,LINQ执行了条件语句并返回了元素的值大于5的元素,并且也省去了复杂的数组遍历。

其实,使用LINQ进行查询之后会返回一个IEnumerable的集合,而IEnumerable是.NET框架中最基本的集合访问器,可以使用foreach语句遍历集合元素。当然,LINQ不仅能够查询数组,还可以通过.NET提供的编程语言进行筛选。例如,对于一个字符串数组str,如果要查询其中包含“C#”的字符串,对于传统的编程方法是非常冗余和烦琐的。但使用LINQ就非常简单,由于LINQ是.NET编程语言中的一部分,开发人员就能通过编程语言进行筛选。如下面的代码所示:


string[]str={"我爱C#","C#新特性","Web.Config","URL"};

var result=from data in str where data.Contains("C#")select data;


除此之外,LINQ语句能够方便地扩展,当有不同的需求时,可以修改条件语句进行逻辑判断。例如,在上面的num数组中,可以筛选一个平方数为偶数的数组元素,直接修改条件即可。LINQ查询语句如下所示:


var result=from data in num where(data*data)%2==0

select data;


上述代码通过条件((dta*data)%2==0将数组元素进行筛选,选择平方数为偶数的数组元素的集合,因此得到的结果是2468。

9.1.2 查询数据库

在数据库操作中,同样可以使用LINQ进行数据库查询。LINQ以其优雅的语法和面向对象的思想能够方便地进行数据库操作。下面的示例演示了如何使用LINQ to SQL查询数据库ASPNET4中工资大于3000的员工。

要使用LINQ to SQL查询数据库,首先需要创建一个LINQ to SQL类文件,如图9-2所示。

figure_0344_0248

图 9-2 选择LINQ to SQL模板

然后,直接将服务资源管理器中的相应表拖放到LINQ to SQL类文件可视化窗口中即可,如图9-3所示。

figure_0345_0249

图 9-3 创建LINQ to SQL类文件

创建好LINQ to SQL类文件后,就可以直接使用LINQ to SQL类文件提供的类进行查询。示例代码如下所示:


EmployeeDataContext lq=new EmployeeDataContext();

var result=from employeeData in lq.Employees

from salaryData in lq.Salaries

where employeeData.employeeid==

salaryData.employeeid

&&salaryData.salary1>3000

select employeeData;

foreach(variin result)

{

Label1.Text+=i.employeename.ToString();

}


如上面的代码所示,在LINQ to SQL类文件中,LINQ to SQL类文件已经将数据库的模型封装成一个对象,开发人员能够通过面向对象的思想访问和整合数据库。如下面的查询语句所示:


var result=from employeeData in lq.Employees

from salaryData in lq.Salaries

where employeeData.employeeid==

salaryData.employeeid

&&salaryData.salary1>3000

select employeeData;


除此之外,LINQ作为编程语言的一部分,还可以使用更多的编程方法实现不同的筛选需求。例如,筛选姓名中包含“马”的员工:


var result=from employeeData in lq.Employees

from salaryData in lq.Salaries

where employeeData.employeeid==

salaryData.employeeid

&&salaryData.salary1>3000

&&employeeData.employeename.Contains("马")

select employeeData;


如上述代码使用了Contains方法判断一个字符串中是否包含某个字符或字符串,这样不仅方便阅读,也简化了查询操作。LINQ返回了符合条件的元素的集合,并实现了筛选操作。

LINQ不仅作为编程语言的一部分,简化了开发人员的开发操作,从另一方面讲,LINQ也补充了在SQL中难以通过几条语句实现的功能的实现。从上面的LINQ查询代码可以看出,就算是不同的对象、不同的数据源,其LINQ基本的查询语法都非常相似,并且LINQ还能够支持编程语言具有的特性,从而弥补SQL语句的不足。在数据集的查询中,其查询语句也可以直接使用而无须大面积修改代码,这样代码就具有了更高的维护性和可读性。

9.1.3 LINQ查询语法概述

从上面的两小节中可以看出,LINQ查询语句能够将复杂的查询应用简化成一个简单的查询语句。不仅如此,LINQ还支持编程语言本有的特性进行高效的数据访问和筛选。虽然LINQ在写法上和SQL语句十分相似,但是LINQ语句在其查询语法上和SQL语句还是有出入的。如下面的SQL查询语句:


select*from employee, salary where

employee.employeeid=salary.Employeeid

and salary.salary>3000


与上面的SQL查询语句相对应的LINQ查询语句格式如下所示:


var result=from employeeData in lq.Employees

from salaryData in lq.Salaries

where employeeData.employeeid==

salaryData.employeeid

&&salaryData.salary1>3000

select employeeData;


上述代码作为LINQ查询语句实现了同SQL查询语句一样的效果,但是LINQ查询语句在格式上与SQL语句不同。LINQ的基本格式如下所示:


var<变量>=from<项目>in<数据源>where<表达式>

orderby<表达式>select<项目>


LINQ语句不仅能够支持对数据源的查询和筛选,同SQL语句一样,它还支持orderby等排序以及投影等操作。示例查询语句如下所示:


var result=from employeeData in lq.Employees

from salaryData in lq.Salaries

where employeeData.employeeid==

salaryData.employeeid

&&salaryData.salary1>3000

&&employeeData.employeename.Contains("马")

orderby salaryData.salary1 descending

select employeeData;


从结构上来看,LINQ查询语句同SQL查询语句中比较大的区别就在于SQL查询语句中的select关键字在语句的前面,而在LINQ查询语句中select关键字在语句的后面,在其他地方没有太大的区别,相信对于熟悉SQL查询语句的人来说非常容易上手。