使用LINQ处理数据.docx
《使用LINQ处理数据.docx》由会员分享,可在线阅读,更多相关《使用LINQ处理数据.docx(29页珍藏版)》请在冰豆网上搜索。
使用LINQ处理数据
使用LINQ处理数据
.NETLanguage-IntegratedQuery(LINQ,语言集成查询)是微软公司提供的一项新技术,它将查询操作直接引入到.NETFramework3.5所支持的编程语言(如C#、VisualBasic等)中,从而直接实现查询功能。
本章将讲解使用LINQ处理的方法,主要介绍以下知识点:
*LINQ概述;
*LINQ查询子句;
*使用LINQ维护User表的数据。
通过本章的学习,读者将可以了解使用LINQ查询集合中的数据的基本操作方法,并使用LINQ处理数据库中的数据的方法。
13.1LINQ概述
查询(Query)是一种从给定的数据源中检索满足指定条件的数据表达式。
查询也是一组指令,这些指令可以从一个或多个给定的数据源中检索数据,并指定检索结果的数据类型和表现形式。
传统上,查询技术往往使用字符串来表示查询操作,如查询关系数据库的SQL语句、查询XML结构数据的XQuery等。
在这些查询操作中,一般不会检查被查询数据的类型。
同时,这些查询操作往往与编程语言处于一种相对孤立的状态。
LINQ(.NETLanguage-IntegratedQuery、语言集成查询)也是一种查询技术,它最大的特点就是能够把查询操作直接引入到.NETFramework3.5所支持的编程语言(如C#、VisualBasic等)中,并整合为一体。
LINQ查询表达式是由一组用类似于SQL或XQuery的声明性语法编写的子句组成。
每一个子句可以包含一个或多个C#表达式,而这些表达式本身又可能是查询表达式或包含查询表达式。
LINQ为.NETFramekwork3.5所支持,它包括以下4个主要组件或技术。
*LINQtoObjects:
查询IEnumerable或IEnumerable类型的集合,即查询任何可枚举的集合,如数组(Array和ArrayList)、泛型列表(List)、字典(Dictionary),以及用户自定义的集合。
*LINQtoSQL:
查询和处理(如插入、修改、删除、排序等操作)基于关系数据库(如SQLServer数据库等)的数据。
*LINQtoDataSet:
查询和处理DataSet对象中的数据,并这些数据进行检索、过滤和排序等操作。
*LINQtoXML:
查询和处理XML结构的数据(如XML文档、XML数据片段、XML格式的字符串等)。
【示例13-1】创建一个简单的LINQ查询表达式query0。
该表达式查询sources数组中小于3的元素。
int[]sources={0,1,2,3,4,5,6,7,8,9};
varquery0=fromvinsources
wherev<3
selectv;
13.2LINQ查询子句
LINQ查询表达式由一组类似于SQL或XQuery的声明性语法编写的子句组成。
每一个子句可以包含一个或多个C#表达式,而这些表达式本身又可能是查询表达式或包含查询表达式。
LINQ查询表达式包含8个基本子句,具体说明如下所述。
*from子句:
指定查询表达式的数据源和范围变量。
*select子句:
指定筛选元素的逻辑条件。
一般由逻辑运算符组成。
*where子句:
指定查询结果的表现形式。
*group子句:
对查询结果进行分组。
*orderby子句:
对查询结果进行排序。
*join子句:
用来连接多个查询操作的数据源。
*let子句:
可以用来引入用于存储子表达式查询结果的范围变量。
*into子句:
提供一个临时标识符,使用该标识可以允许对join、group或select子句结果的引用。
13.2.1from子句
from子句和SQL语句中的“FROM子句”比较相似,它可以指定查询的数据源(也包括子查询的数据源)和范围变量。
其中,范围变量用来表示数据源序列中的每一个元素。
?
注意:
LINQ查询表达式必须包含from子句,且以from子句开头。
【示例13-2】创建了一个LINQ查询表达式,并保存为query1。
该表达式从sources数组中查询小于2的元素。
?
注意:
s为范围变量。
sources为数据源,它为整型数组,并包含10个值。
int[]sources={0,1,2,3,4,5,6,7,8,9};
varquery1=fromsinsources
wheres<2
selects;
示例13-2的查询结果如表13.1所示。
表13.1示例13-2的查询结果表
数据源
查询表达式
查询结果
sources(包含9个元素,分别为0、1、2、3、4、5、6、7、8、9)
fromsinsources
wheres<2
selects;
query1(包含两个元素,分别为0和1)
【示例13-3】创建了一个LINQ查询表达式,并保存为query2。
该表达式从strs字符串中查询a字符到g之间的字符。
?
注意:
c为范围变量。
strs为数据源,它为一个字符串,值为“Thisisastring.”。
stringstrs="Thisisastring.";
varquery2=fromcinstrs
wherec<='g'&&c>='a'
selectc;
示例13-3的查询结果如表13.2所示。
表13.2示例13-3的查询结果表
数据源
查询表达式
查询结果
strs,值为“Thisisastring.”
fromcinstrs
wherec<='g'&&c>='a'
selectc;
query2(包含两个元素,分别为“a”和“g”)
?
注意:
from子句指定数据源的类型必须为IEnumerable、IEnumerable或前两者的派生类型。
根据from子句的数量和组合方式,可以把LINQ查询表达式分为以下3种类型。
*单个from子句查询表达式。
*多个from子句查询表达式。
*复合from子句查询表达式。
1.单个from子句查询
若LINQ查询表达式只包含一个from子句,则称该查询为单个from子句查询。
一般情况下,单个from子句查询往往使用一个数据源。
【示例13-4】创建了一个LINQ查询表达式,并保存为query3。
该表达式从strs字符串中查询a字符到c之间的字符。
stringstrs="Thisisastring.";
varquery3=fromcinstrs
wherec<='c'&&c>='a'
selectc;
示例13-4的查询结果如表13.3所示。
表13.3示例13-4的查询结果表
数据源
查询表达式
查询结果
strs,值为“Thisisastring.”
fromcinstrs
wherec<='c'&&c>='a'
selectc;
query3(包含1个元素,为“a”)
2.多个from子句查询
若LINQ查询表达式包含多个from子句,则称该查询为多个from子句查询。
一般情况下,包含多个from子句的查询往往使用多个数据源。
【示例13-5】创建了一个LINQ查询表达式,并保存为query4。
该表达式从sourcesa数组中查询小于2的元素,并从sourcesb数组中查询大于100的元素,并计算两个查询的和。
int[]sourcesa={0,1,2,3,4,5,6,7,8,9};
int[]sourcesb={100,200,300,400,2008};
varquery4=fromsinsourcesa
wheres<2
fromiinsourcesb
wherei>100
selects+i;
示例13-5的查询结果如表13.4所示。
表13.4示例13-5的查询结果表
数据源
查询表达式
查询结果
sourcesa(包含9个元素,分别为0、1、2、3、4、5、6、7、8、9)
sourcesb(包括5个元素,分别为100、200、300、400、2008)
fromsinsourcesa
wheres<2
fromiinsourcesb
wherei>100
selects+i;
query4(包含8个元素,分别为200、300、400、2008、201、301、401、2009)
3.复合from子句查询
在一些情况下,数据源的元素也是一个数据源(被称为子数据源)。
如果要查询子数据源中的元素,则需要使用复合from子句。
【示例13-6】创建了一个LINQ查询表达式,并保存为query5。
该表达式首先从sources字符数组中查询包含string的字符串(使用“fromsinsources”子句),然后从该字符串中查询a字符到g之间的字符(使用“fromcins”子句)。
最后,输出查询结果的字符及其所在的字符串。
string[]sources={"Thisisastring.","Thisisabook."};
varquery5=fromsinsources
fromcins
wheres.IndexOf("string")>-1&&c<='g'&&c>='a'
selectc+":
"+s;
示例13-6的查询结果如表13.5所示。
表13.5示例13-6的查询结果表
数据源
查询表达式
查询结果
sources(包含2个元素,分别为“Thisisastring.”和“Thisisabook.”)
fromsinsources
fromcins
wheres.IndexOf("string")>-1&&c<='g'&&c>='a'
selectc+":
"+s;
query5(包含2个元素,分别为“a:
Thisisastring.”和“g:
Thisisastring.”)
13.2.2where子句
where子句和SQL语句中的“WHERE子句”比较相似,它指定查询表达式的筛选元素满足的逻辑条件。
where子句一般由逻辑运算符(如逻辑“与”、逻辑“或”)组成。
一个查询表达式可以包含1个或多个where子句,甚至不包含where子句。
每一个where子句可以包含1个或多个布尔条件表达式。
?
注意:
对LINQ查询表达式而言,where子句不是必须的。
如果LINQ查询表达式包含了where子句,那么where子句不能为LINQ查询表达式的第一个子句或最后一个子句。
【示例13-7】创建了一个LINQ查询表达式,并保存为query6。
该表达式从sources数组中查询大于3的元素。
int[]sources={0,1,2,3,4,5,6,7,8,9};
varquery6=fromsinsources
wheres>3
selects;
示例13-7的查询结果如表13.6所示。
表13.6示例13-7的查询结果表
数据源
查询表达式
查询结果
sources(包含9个元素,分别为0、1、2、3、4、5、6、7、8、9)
fromsinsources
wheres>3
selects;
query6(包含6个元素,分别为4、5、6、7、8、9)
【示例13-8】创建了一个LINQ查询表达式,并保存为query7。
该表达式从sources数组中查询大于3且小于8的元素。
int[]sources={0,1,2,3,4,5,6,7,8,9};
varquery7=fromsinsources
wheres>3&&s<8
selects;
示例13-8的查询结果如表13.7所示。
表13.7示例13-8的查询结果表
数据源
查询表达式
查询结果
sources(包含9个元素,分别为0、1、2、3、4、5、6、7、8、9)
fromsinsources
wheres>3&&<8
selects;
query7(包含4个元素,分别为4、5、6、7)
13.2.3select子句
select子句和SQL语句中的“SELECT子句”比较相似,它可以指定查询结果的类型和表现形式。
一个LINQ查询表达式可以不包含select子句,也可以包含1个select子句。
?
注意:
LINQ查询表达式要么以select子句结束,要么以group子句结束。
【示例13-9】创建了一个LINQ查询表达式,并保存为query8。
该表达式从sources数组中查询大于7的元素。
int[]sources={0,1,2,3,4,5,6,7,8,9};
varquery8=fromsinsources
wheres>7
selects;
示例13-9的查询结果如表13.8所示。
表13.8示例13-9的查询结果表
数据源
查询表达式
查询结果
sources(包含9个元素,分别为0、1、2、3、4、5、6、7、8、9)
fromsinsources
wheres>7
selects;
query8(包含2个元素,分别为8和9)
【示例13-10】创建了一个LINQ查询表达式,并保存为query9。
该表达式从sources数组中查询小于3的元素,并返回查询结果的元素与100的乘积。
int[]sources={0,1,2,3,4,5,6,7,8,9};
varquery9=fromsinsources
wheres<3
selects*100;
示例13-10的查询结果如表13.9所示。
表13.9示例13-10的查询结果表
数据源
查询表达式
查询结果
sources(包含9个元素,分别为0、1、2、3、4、5、6、7、8、9)
fromsinsources
wheres<3
selects*100;
query8(包含3个元素,分别为0、100、200)
【示例13-11】创建了一个LINQ查询表达式,并保存为query10。
该表达式从sources数组中查询小于3的元素,并返回新对象。
其中,新对象的ID属性值为查询结果的元素值;Username属性的值则由“User”字符串和查询结果的元素的值组成。
int[]sources={0,1,2,3,4,5,6,7,8,9};
varquery10=fromsinsources
wheres<3
selectnew
{
ID=s,
Username="User"+s.ToString()
};
示例13-11的查询结果如表13.10所示。
表13.10示例13-11的查询结果表
数据源
查询表达式
查询结果
sources(包含9个元素,分别为0、1、2、3、4、5、6、7、8、9)
fromsinsources
wheres<3
selectnewUserInfo
{
ID=s,
Username="User"+s.ToString()
};;
query10(包含3个元素,元素的ID属性的值分别为0、1、2)
13.2.4group子句
group子句可以对查询的结果进行分组,并返回元素类型为IGrouping的对象序列。
其中,TKey参数指定元素的键的类型,TElement参数指定元素的值的类型。
?
注意:
IGrouping和IEnumerable非常相似,在此不做详细介绍。
【示例13-12】创建了一个LINQ查询表达式,并保存为query11。
该表达式从sources数组中查询元素,并按照元素的奇偶性进行分组。
int[]sources={0,1,2,3,4,5,6,7,8,9};
varquery11=fromsinsources
groupsbys%2==0;
【示例13-13】使用2个foreach语句输出了query11查询的结果。
第1个foreach语句枚举query11查询结果中的所有的组,第2个foreach语句枚举每一个组中的每一个元素。
foreach(varqinquery11)
{
foreach(varsubqinq)
{
Response.Write(subq.ToString()+",");
}
Response.Write("
");
}
13.2.5orderby子句
orderby子句可以按照关键字(或键)对查询结果进行排序,其中,排序方式可以为“升序”或“降序”,排序的关键字(或键)可以为一个或多个。
?
注意:
order子句的默认排序方式为“升序”。
【示例13-14】创建了一个LINQ查询表达式,并保存为query12。
该表达式从sources数组中查询大于7的元素,并按照元素进行升序排序。
int[]sources={0,1,2,3,4,5,6,7,8,9};
varquery12=fromsinsources
wheres>7
orderbys
selects;
示例13-14的查询结果如表13.11所示。
表13.11示例13-14的查询结果表
数据源
查询表达式
查询结果
sources(包含9个元素,分别为0、1、2、3、4、5、6、7、8、9)
fromsinsources
wheres>7
orderbys
selects;
query12(包含2个元素,分别为8和9)
【示例13-15】创建了一个LINQ查询表达式,并保存为query13。
该表达式从sources数组中查询元素,并按照元素的奇偶性进行分组。
其中,每一个分组都按照元素的值进行倒序排序。
int[]sources={0,1,2,3,4,5,6,7,8,9};
varquery13=fromsinsources
orderbysdescending
groupsbys%2==0;
13.2.6into子句
into子句可以创建一个临时标识符,使用该标识符可以存储group、join或select子句查询结果。
【示例13-16】创建了一个LINQ查询表达式,并保存为query14。
该查询表达式的具体操作说明如下所述。
*从sources数组中查询元素。
*按照元素的奇偶性进行分组。
*每一个分组中的元素都按照元素的值进行倒序排序。
*将每一个查询结果临时保存为g变量。
*使用where子句判断查询g变量中的元素数量是否大于5,如果大于5,则选择该组。
int[]sources={0,1,2,3,4,5,6,7,8,9,10};
varquery14=fromsinsources
orderbysdescending
groupsbys%2==0intog
whereg.Count()>5
selectg;
示例13-16的查询结果如表13.12所示。
表13.12示例13-16的查询结果表
数据源
查询表达式
查询结果
sources(包含10个元素,分别为0、1、2、3、4、5、6、7、8、9、10)
fromsinsources
orderbysdescending
groupsbys%2==0intog
whereg.Count()>5
selectg;
query14(包含1个元素,该元素为一个组,组内包含6个元素,分别为10、8、6、4、2、0)
13.2.7let子句
let子句可以创建一个范围变量,使用该变量可以保存表达式中的中间结果。
?
注意:
let子句创建的范围变量的值只能通过初始化操作进行赋值。
范围变量的值一旦被初始化,将不能再被改变。
【示例13-17】创建了一个LINQ查询表达式,并保存为query15。
该查询表达式的具体操作说明如下所述。
*从sources数组中查询元素。
*使用let语句创建范围变量m,它的值为元素除以2的余数。
*查询元素的值大于3,且m变量的值等于1的元素。
int[]sources={0,1,2,3,4,5,6,7,8,9};
varquery15=fromsinsources
letm=s%2
wheres>3&&m==1
selects;
示例13-17的查询结果如表13.13所示。
表13.13示例13-17的查询结果表
数据源
查询表达式
查询结果
sources(包含9个元素,分别为0、1、2、3、4、5、6、7、8、9)
fromsinsources
letm=s%2
wheres>3&&m==1
selects;
query15(包含3个元素,分别为5、7和9)
13.2.8join子句
join子句可以设置两个或多个存在相关属性或值的数据源之间的关系。
join子句可以为数据源之间建立以下3种联接关系。
*内部联接,和SQL语句中的“INNERJOIN子句”比较相似,两个数据源都必须存在相同的值,即两个数据源都必须存在满足联接关系的元素。
*分组联接,即为含有into子句的join子句。
*左外部联接,和SQL语句中的“INNERLEFT子句”比较相似。
【示例13-18】创建两个类:
UserInfo和Role-Info。
UserInfo类描述用户的信息,包含3个属性:
ID、RoleID和Username。
RoleInfo类描述角色的信息,包含2个属性:
ID和RoleName。
UserInfo和RoleInfo类的类关系图如图13.1所示。
?
注意:
UserInfo类的RoleID属性的值是引用于RoleInfo类的ID属性。
因此,UserInfo类的RoleID属性和RoleInfo类的ID属性将建立联接关系。
//