LINQ.docx
- 文档编号:26081854
- 上传时间:2023-06-17
- 格式:DOCX
- 页数:17
- 大小:35.30KB
LINQ.docx
《LINQ.docx》由会员分享,可在线阅读,更多相关《LINQ.docx(17页珍藏版)》请在冰豆网上搜索。
LINQ
LINQ介绍
语言集成查询(LINQ)是VisualStudio2008和.NETFramework3.5版中引入的一项创新功能,它在对象领域和数据领域之间架起了一座桥梁。
传统上,针对数据的查询都是以简单的字符串表示,而没有编译时类型检查或IntelliSense支持。
此外,您还必须针对以下各种数据源学习一种不同的查询语言:
SQL数据库、XML文档、各种Web服务等等。
LINQ使查询成为C#和VisualBasic中的一流语言构造。
您可以使用语言关键字和熟悉的运算符针对强类型化对象集合编写查询。
下图显示了一个用C#语言编写的、不完整的LINQ查询,该查询针对SQLServer数据库,并具有完全类型检查和IntelliSense支持。
在VisualStudio中,可以用VisualBasic或C#为以下数据源编写LINQ查询:
SQLServer数据库、XML文档、ADO.NET数据集,以及支持IEnumerable或泛型IEnumerable(OfT)接口的任意对象集合。
此外,还计划了对ADO.NETEntityFramework的LINQ支持,并且第三方为许多Web服务和其他数据库实现编写了LINQ提供程序。
LINQ查询既可在新项目中使用,也可在现有项目中与非LINQ查询一起使用。
唯一的要求是项目应面向.NETFramework3.5或更高版本。
基本LINQ查询操作
本主题简要介绍LINQ查询表达式,以及您在查询中执行的一些典型类型的操作。
下面各主题中提供了更详细的信息:
LINQ查询表达式(C#编程指南)
标准查询运算符概述
注意
如果您已熟悉查询语言(如SQL或XQuery),则可以跳过本主题的大部分内容。
阅读下一节中的“from子句”来了解LINQ查询表达式中的子句的顺序。
获取数据源
--------------------------------------------------------------------------------
在LINQ查询中,第一步是指定数据源。
像在大多数编程语言中一样,在C#中,必须先声明变量,才能使用它。
在LINQ查询中,最先使用from子句的目的是引入数据源(customers)和范围变量(cust)。
C#复制
//queryAllCustomersisanIEnumerable
varqueryAllCustomers=fromcustincustomers
selectcust;
范围变量类似于foreach循环中的迭代变量,但在查询表达式中,实际上不发生迭代。
执行查询时,范围变量将用作对customers中的每个后续元素的引用。
因为编译器可以推断cust的类型,所以您不必显式指定此类型。
其他范围变量可由let子句引入。
有关更多信息,请参见let子句(C#参考)。
注意
对于非泛型数据源(如ArrayList),必须显式类型化范围变量。
有关更多信息,请参见如何:
使用LINQ查询ArrayList和from子句(C#参考)。
筛选
--------------------------------------------------------------------------------
也许最常用的查询操作是应用布尔表达式形式的筛选器。
此筛选器使查询只返回那些表达式结果为true的元素。
使用where子句生成结果。
实际上,筛选器指定从源序列中排除哪些元素。
在下面的示例中,只返回那些地址位于伦敦的customers。
C#复制
varqueryLondonCustomers=fromcustincustomers
wherecust.City=="London"
selectcust;
您可以使用熟悉的C#逻辑AND和OR运算符来根据需要在where子句中应用任意数量的筛选表达式。
例如,若要只返回位于“伦敦”AND姓名为“Devon”的客户,您应编写下面的代码:
C#复制
wherecust.City=="London"&&cust.Name=="Devon"
若要返回位于伦敦或巴黎的客户,您应编写下面的代码:
C#复制
wherecust.City=="London"||cust.City=="Paris"
有关更多信息,请参见where子句(C#参考)。
Ordering
--------------------------------------------------------------------------------
通常可以很方便地将返回的数据进行排序。
orderby子句将使返回的序列中的元素按照被排序的类型的默认比较器进行排序。
例如,下面的查询可以扩展为按Name属性对结果进行排序。
因为Name是一个字符串,所以默认比较器执行从A到Z的字母排序。
C#复制
varqueryLondonCustomers3=
fromcustincustomers
wherecust.City=="London"
orderbycust.Nameascending
selectcust;
若要按相反顺序(从Z到A)对结果进行排序,请使用orderby…descending子句。
有关更多信息,请参见orderby子句(C#参考)。
分组
--------------------------------------------------------------------------------
使用group子句,您可以按指定的键分组结果。
例如,您可以指定结果应按City分组,以便位于伦敦或巴黎的所有客户位于各自组中。
在本例中,cust.City是键。
注意
在下面的示例中,类型是显式的以更好地说明概念。
您也可以对custQuery、group和customer使用隐式类型以让编译器确定准确的类型。
C#复制
//queryCustomersByCityisanIEnumerable
varqueryCustomersByCity=
fromcustincustomers
groupcustbycust.City;
//customerGroupisanIGrouping
foreach(varcustomerGroupinqueryCustomersByCity)
{
Console.WriteLine(customerGroup.Key);
foreach(CustomercustomerincustomerGroup)
{
Console.WriteLine(" {0}",customer.Name);
}
}
在使用group子句结束查询时,结果采用列表的列表形式。
列表中的每个元素是一个具有Key成员及根据该键分组的元素列表的对象。
在循环访问生成组序列的查询时,您必须使用嵌套的foreach循环。
外部循环用于循环访问每个组,内部循环用于循环访问每个组的成员。
如果您必须引用组操作的结果,可以使用into关键字来创建可进一步查询的标识符。
下面的查询只返回那些包含两个以上的客户的组:
C#复制
//custQueryisanIEnumerable
varcustQuery=
fromcustincustomers
groupcustbycust.CityintocustGroup
wherecustGroup.Count()>2
orderbycustGroup.Key
selectcustGroup;
有关更多信息,请参见group子句(C#参考)。
联接
--------------------------------------------------------------------------------
联接运算创建数据源中没有显式建模的序列之间的关联。
例如,您可以执行联接来查找位于同一地点的所有客户和经销商。
在LINQ中,join子句始终针对对象集合而非直接针对数据库表运行。
C#复制
varinnerJoinQuery=
fromcustincustomers
joindistindistributorsoncust.Cityequalsdist.City
selectnew{CustomerName=cust.Name,DistributorName=dist.Name};
在LINQ中,您不必像在SQL中那样频繁使用join,因为LINQ中的外键在对象模型中表示为包含项集合的属性。
例如,Customer对象包含Order对象的集合。
不必执行联接,只需使用点表示法访问订单:
使用LINQ进行数据转换(C#)
语言集成查询(LINQ)不仅可用于检索数据,
而且还是一个功能强大的数据转换工具。
通过使用LINQ查询,您可以将源序列用作输入,并采用多种方式修改它以创建新输出序列。
您可以通过排序和分组来修改序列本身,而不必修改元素本身。
但是,LINQ查询的最强大功能可能在于它能够创建新类型。
这一功能在
select
子句中实现。
例如,可以执行下列任务:
∙
将多个输入序列合并到具有新类型的单个输出序列中。
∙
创建其元素只包含源序列中的各个元素的一个或几个属性的输出序列。
∙
创建其元素包含对源数据执行的操作结果的输出序列。
∙
创建不同格式的输出序列。
例如,您可以将SQL行或文本文件的数据转换为XML。
这只是几个示例。
当然,可以采用多种方式将这些转换组合在同一查询中。
另外,一个查询的输出序列可用作新查询的输入序列。
将多个输入联接到一个输出序列
可以使用LINQ查询来创建包含多个输入序列的元素的输出序列。
下面的示例演示如何组合两个内存中的数据结构,但组合来自XML或SQL或数据集源的数据时可应用相同的原则。
假定下面两种类类型:
C#
classStudent
{
public
stringFirst{get;set;}
public
stringLast{get;set;}
public
intID{get;set;}
public
stringStreet{get;set;}
public
stringCity{get;set;}
publicList
}
classTeacher
{
public
stringFirst{get;set;}
public
stringLast{get;set;}
public
intID{get;set;}
public
stringCity{get;set;}
}
下面的示例演示该查询:
C#
classDataTransformations
{
static
voidMain()
{
//Createthefirstdatasource.
List
{
newStudent{First="Svetlana",
Last="Omelchenko",
ID=111,
Street="123MainStreet",
City="Seattle",
Scores=newList
newStudent{First="Claire",
Last="O’Donnell",
ID=112,
Street="124MainStreet",
City="Redmond",
Scores=newList
newStudent{First="Sven",
Last="Mortensen",
ID=113,
Street="125MainStreet",
City="LakeCity",
Scores=newList
};
//Createtheseconddatasource.
List
{
newTeacher{First="Ann",Last="Beebe",ID=945,City="Seattle"},
newTeacher{First="Alex",Last="Robinson",ID=956,City="Redmond"},
newTeacher{First="Michiyo",Last="Sato",ID=972,City="Tacoma"}
};
//Createthequery.
varpeopleInSeattle=(fromstudentinstudents
wherestudent.City=="Seattle"
selectstudent.Last)
.Concat(fromteacherinteachers
whereteacher.City=="Seattle"
selectteacher.Last);
Console.WriteLine("ThefollowingstudentsandteachersliveinSeattle:
");
//Executethequery.
foreach(varpersoninpeopleInSeattle)
{
Console.WriteLine(person);
}
Console.WriteLine("Pressanykeytoexit.");
Console.ReadKey();
}
}
/*Output:
ThefollowingstudentsandteachersliveinSeattle:
Omelchenko
Beebe
*/
选择各个源元素的子集
选择源序列中的各个元素的子集有两种主要方法:
1.
若要只选择源元素的一个成员,请使用点运算。
在下面的示例中,假定Customer对象包含几个公共属性,其中包括名为City的字符串。
在执行此查询时,此查询将生成字符串输出序列。
other
varquery=fromcustinCustomers
selectcust.City;
2.
若要创建包含源元素的多个属性的元素,可以使用具有命名对象或匿名类型的对象初始值设定项。
下面的示例演示如何使用匿名类型来封装各个Customer元素的两个属性:
other
varquery=fromcustinCustomer
selectnew{Name=cust.Name,City=cust.City};
将内存中的对象转换为XML
通过LINQ查询,可以轻松地在内存中的数据结构、SQL数据库、ADO.NET数据集和XML流或文档之间转换数据。
下面的示例将内存中的数据结构中的对象转换为XML元素。
C#
classXMLTransform
{
static
voidMain()
{
//Createthedatasourcebyusingacollectioninitializer.
List
{
newStudent{First="Svetlana",Last="Omelchenko",ID=111,Scores=newList
newStudent{First="Claire",Last="O’Donnell",ID=112,Scores=newList
newStudent{First="Sven",Last="Mortensen",ID=113,Scores=newList
};
//Createthequery.
varstudentsToXML=newXElement("Root",
fromstudentinstudents
letx=String.Format("{0},{1},{2},{3}",student.Scores[0],
student.Scores[1],student.Scores[2],student.Scores[3])
select
newXElement("student",
newXElement("First",student.First),
newXElement("Last",student.Last),
newXElement("Scores",x)
)//end"student"
);//end"Root"
//Executethequery.
Console.WriteLine(studentsToXML);
//Keeptheconsoleopenindebugmode.
Console.WriteLine("Pressanykeytoexit.");
Console.ReadKey();
}
}
此代码生成下面的XML输出:
other
对源元素执行操作
输出序列可能不包含源序列的任何元素或元素属性。
输出可能是通过将源元素用作输入参数计算出的值的序列。
在执行下面这个简单查询时,此查询会输出一个字符串序列,该序列值表示根据double类型的元素的源序列进行的计算。
注意
如果查询将转换为某个其他域,则不支持在查询表达式中调用方法。
例如,不能在LINQtoSQL中调用一般C#方法,因为SQLServer没有该方法的上下文。
但是,可以将存储过程映射到方法,然后调用方法。
C#
classFormatQuery
{
static
voidMain()
{
//Datasource.
double[]radii={1,2,3};
//Query.
IEnumerable
fromradinradii
selectString.Format("Area={0}",(rad*rad)*3.14);
//Queryexecution.
foreach(stringsinquery)
Console.WriteLine(s);
//Keeptheconsoleopenindebugmode.
Console.WriteLine("Pressanykeytoexit.");
Console.ReadKey();
}
}
/*Output:
Area=3.14
Area=12.56
Area=28.26
*/
LINQ和泛型类型(C#)
LINQ查询基于泛型类型,在.NETFramework的2.0版中引入了泛型类型。
您无需深入了解泛型即可开始编写查询。
但是,您可能需要了解两个基本概念:
1.
当您创建泛型集合类(如
List(OfT))的实例时,您将“T”替换为列表将包含的对象的类型。
例如,字符串列表表示为List
泛型列表是强类型的,且提供了比将其元素存储为
Object
的集合更多的好处。
如果您尝试将Customer添加到List
泛型集合易于使用的原因是您不必执行运行时类型强制转换。
2.
IEnumerable(OfT)
是一个接口,通过该接口,可以使用foreach语句来枚举泛型集合类。
泛型集合类支持
IEnumerable(OfT),就像非泛型集合类(如
ArrayList)支持
IEnumerable。
LINQ查询中的IEnumerable
LINQ查询变量类型化为
IEnumerable(OfT)
或派生类型,如
IQueryable(OfT)。
当您看到类型化为IEnumerable
C#
IEnumerable
fromcustincustomers
wherecust.City=="London"
selectcust;
foreach(CustomercustomerincustomerQuery)
{
Console.WriteLi
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- LINQ