您的位置:首页 > 其它

LINQ(二)基本 LINQ 查询操作

2014-10-18 12:27 513 查看

本文讲述了linq查询常用的from/where/orderby/groupby/join/where字句的用法。

获取数据源&from

在LINQ查询中,第一步是指定数据源。像在大多数编程语言中一样,在C#
中,必须先声明变量,才能使用它。在LINQ
查询中,最先使用from子句的目的是引入数据源(customers)
和范围变量(cust)。

C#


//queryAllCustomersisanIEnumerable<Customer>

varqueryAllCustomers=fromcustincustomers

selectcust;



范围变量类似于foreach循环中的迭代变量,但在查询表达式中,实际上不发生迭代。执行查询时,范围变量将用作对customers中的每个后续元素的引用。因为编译器可以推断cust的类型,所以您不必显式指定此类型。



筛选&where

也许最常用的查询操作是应用布尔表达式形式的筛选器。此筛选器使查询只返回那些表达式结果为true
的元素。使用where子句生成结果。实际上,筛选器指定从源序列中排除哪些元素。在下面的示例中,只返回那些地址位于伦敦的customers。

C#


varqueryLondonCustomers=fromcustincustomers

wherecust.City=="London"

selectcust;



您可以使用熟悉的C#逻辑ANDOR运算符来根据需要在where子句中应用任意数量的筛选表达式。例如,若要只返回位于“伦敦”AND姓名为“Devon”的客户,您应编写下面的代码:

C#


wherecust.City=="London"&&cust.Name=="Devon"



若要返回位于伦敦或巴黎的客户,您应编写下面的代码:

C#


wherecust.City=="London"||cust.City=="Paris"


Orderby

通常可以很方便地将返回的数据进行排序。orderby子句将使返回的序列中的元素按照被排序的类型的默认比较器进行排序。例如,下面的查询可以扩展为按Name属性对结果进行排序。因为Name是一个字符串,所以默认比较器执行从
A到Z的字母排序。

C#


varqueryLondonCustomers3=

fromcustincustomers

wherecust.City=="London"

orderbycust.Nameascending

selectcust;



若要按相反顺序(从Z
到A)对结果进行排序,请使用orderby…descending子句。



分组&groupby

使用group子句,您可以按指定的键分组结果。例如,您可以指定结果应按City分组,以便位于伦敦或巴黎的所有客户位于各自组中。在本例中,cust.City是键。

C#


//queryCustomersByCityisanIEnumerable<IGrouping<string,Customer>>

varqueryCustomersByCity=

fromcustincustomers

groupcustbycust.City;


//customerGroupisanIGrouping<string,Customer>

foreach(varcustomerGroupinqueryCustomersByCity)

{

Console.WriteLine(customerGroup.Key);

foreach(CustomercustomerincustomerGroup)

{

Console.WriteLine("{0}",customer.Name);

}

}



在使用group子句结束查询时,结果采用列表的列表形式。列表中的每个元素是一个具有Key成员及根据该键分组的元素列表的对象。在循环访问生成组序列的查询时,您必须使用嵌套的foreach循环。外部循环用于循环访问每个组,内部循环用于循环访问每个组的成员。

【如果您必须引用组操作的结果,可以使用into关键字来创建可进一步查询的标识符。下面的查询只返回那些包含两个以上的客户的组:

C#


//custQueryisanIEnumerable<IGrouping<string,Customer>>

varcustQuery=

fromcustincustomers

groupcustbycust.CityintocustGroup

wherecustGroup.Count()>2

orderbycustGroup.Key

selectcustGroup;





联接jion

联接运算创建数据源中没有显式建模的序列之间的关联。例如,您可以执行联接来查找位于同一地点的所有客户和经销商。在
LINQ中,join子句始终针对对象集合而非直接针对数据库表运行。

有关更多信息,请参见join
子句(C#参考)。



选择(投影)&select子句

在查询表达式中,select子句可以指定将在执行查询时产生的值的类型。该子句的结果将基于前面所有子句的计算结果以及select子句本身中的所有表达式。查询表达式必须以select子句或group子句结束。

下面的示例演示了查询表达式中的简单select子句。
C#

classSelectSample1
{
static
voidMain()
{
//Createthedatasource
List<int>Scores=
newList<int>(){97,92,81,60};

//Createthequery.
IEnumerable<int>queryHighScores=
fromscore
inScores
wherescore>80
selectscore;

//Executethequery.
foreach(inti
inqueryHighScores)
{
Console.Write(i+"");
}
}
}
在最简单的情况下,select子句仅指定范围变量,这会使返回的序列包含与数据源具有相同类型的元素。不过,select子句还提供了一种功能强大的机制,可用于将源数据转换(或投影)为新类型。下面的示例演示了select子句可能采用的所有不同形式。在每个查询中,请注意select子句和查询变量(studentQuery1、studentQuery2等)的类型之间的关系。

C#

classSelectSample2
{
//Definesomeclasses
public
classStudent
{
public
stringFirst{get;
set;}
public
stringLast{get;
set;}
public
intID{get;set;}
publicList<int>Scores;
publicContactInfoGetContactInfo(SelectSample2app,
intid)
{
ContactInfocInfo=
(fromci
inapp.contactList
whereci.ID==id
selectci)
.FirstOrDefault();

returncInfo;
}

public
overridestringToString()
{
returnFirst+
""+Last+":"+ID;
}
}

public
classContactInfo
{
public
intID{get;set;}
public
stringEmail{get;
set;}
public
stringPhone{get;
set;}
public
overridestringToString(){
returnEmail+","+Phone;}
}

public
classScoreInfo
{
public
doubleAverage{get;
set;}
public
intID{get;set;}
}

//Theprimarydatasource
List<Student>students=newList<Student>()
{
newStudent{First="Svetlana",Last="Omelchenko",ID=111,Scores=
newList<int>(){97,92,81,60}},
newStudent{First="Claire",Last="O'Donnell",ID=112,Scores=
newList<int>(){75,84,91,39}},
newStudent{First="Sven",Last="Mortensen",ID=113,Scores=
newList<int>(){88,94,65,91}},
newStudent{First="Cesar",Last="Garcia",ID=114,Scores=
newList<int>(){97,89,85,82}},
};

//Separatedatasourceforcontactinfo.
List<ContactInfo>contactList=
newList<ContactInfo>()
{
newContactInfo{ID=111,Email="SvetlanO@Contoso.com",Phone="206-555-0108"},
newContactInfo{ID=112,Email="ClaireO@Contoso.com",Phone="206-555-0298"},
newContactInfo{ID=113,Email="SvenMort@Contoso.com",Phone="206-555-1130"},
newContactInfo{ID=114,Email="CesarGar@Contoso.com",Phone="206-555-0521"}
};


static
voidMain(string[]args)
{
SelectSample2app=newSelectSample2();

//ProduceafilteredsequenceofunmodifiedStudents.
IEnumerable<Student>studentQuery1=
fromstudent
inapp.students
wherestudent.ID>111
selectstudent;

Console.WriteLine("Query1:selectrange_variable");
foreach(Students
instudentQuery1)
{
Console.WriteLine(s.ToString());
}

//Produceafilteredsequenceofelementsthatcontain
//onlyonepropertyofeachStudent.
IEnumerable<String>studentQuery2=
fromstudent
inapp.students
wherestudent.ID>111
selectstudent.Last;

Console.WriteLine("\r\nstudentQuery2:selectrange_variable.Property");
foreach(strings
instudentQuery2)
{
Console.WriteLine(s);
}

//Produceafilteredsequenceofobjectscreatedby
//amethodcalloneachStudent.
IEnumerable<ContactInfo>studentQuery3=
fromstudent
inapp.students
wherestudent.ID>111
selectstudent.GetContactInfo(app,student.ID);

Console.WriteLine("\r\nstudentQuery3:selectrange_variable.Method");
foreach(ContactInfoci
instudentQuery3)
{
Console.WriteLine(ci.ToString());
}

//Produceafilteredsequenceofintsfrom
//theinternalarrayinsideeachStudent.
IEnumerable<int>studentQuery4=
fromstudent
inapp.students
wherestudent.ID>111
selectstudent.Scores[0];

Console.WriteLine("\r\nstudentQuery4:selectrange_variable[index]");
foreach(inti
instudentQuery4)
{
Console.WriteLine("Firstscore={0}",i);
}

//Produceafilteredsequenceofdoubles

//thataretheresultofanexpression.
IEnumerable<double>studentQuery5=
fromstudent
inapp.students
wherestudent.ID>111
selectstudent.Scores[0]*1.1;

Console.WriteLine("\r\nstudentQuery5:selectexpression");
foreach(doubled
instudentQuery5)
{
Console.WriteLine("Adjustedfirstscore={0}",d);
}

//Produceafilteredsequenceofdoublesthatare
//theresultofamethodcall.
IEnumerable<double>studentQuery6=
fromstudent
inapp.students
wherestudent.ID>111
selectstudent.Scores.Average();

Console.WriteLine("\r\nstudentQuery6:selectexpression2");
foreach(doubled
instudentQuery6)
{
Console.WriteLine("Average={0}",d);
}

//Produceafilteredsequenceofanonymoustypes
//thatcontainonlytwopropertiesfromeachStudent.
varstudentQuery7=
fromstudent
inapp.students
wherestudent.ID>111
select
new{student.First,student.Last};

Console.WriteLine("\r\nstudentQuery7:selectnewanonymoustype");
foreach(varitem
instudentQuery7)
{
Console.WriteLine("{0},{1}",item.Last,item.First);
}

//Produceafilteredsequenceofnamedobjectsthatcontain
//amethodreturnvalueandapropertyfromeachStudent.
//Usenamedtypesifyouneedtopassthequeryvariable

//acrossamethodboundary.
IEnumerable<ScoreInfo>studentQuery8=
fromstudent
inapp.students
wherestudent.ID>111
select
newScoreInfo
{
Average=student.Scores.Average(),
ID=student.ID
};

Console.WriteLine("\r\nstudentQuery8:selectnewnamedtype");
foreach(ScoreInfosi
instudentQuery8)
{
Console.WriteLine("ID={0},Average={1}",si.ID,si.Average);
}

//Produceafilteredsequenceofstudentswhoappearonacontactlist
//andwhoseaverageisgreaterthan85.
IEnumerable<ContactInfo>studentQuery9=
fromstudent
inapp.students
wherestudent.Scores.Average()>85
joinci
inapp.contactListonstudent.ID
equalsci.ID
selectci;

Console.WriteLine("\r\nstudentQuery9:selectresultofjoinclause");
foreach(ContactInfoci
instudentQuery9)
{
Console.WriteLine("ID={0},Email={1}",ci.ID,ci.Email);
}

//Keeptheconsolewindowopenindebugmode
Console.WriteLine("Pressanykeytoexit.");
Console.ReadKey();
}
}
/*Output
Query1:selectrange_variable
ClaireO'Donnell:112
SvenMortensen:113
CesarGarcia:114

studentQuery2:selectrange_variable.Property
O'Donnell
Mortensen
Garcia

studentQuery3:selectrange_variable.Method
ClaireO@Contoso.com,206-555-0298
SvenMort@Contoso.com,206-555-1130
CesarGar@Contoso.com,206-555-0521

studentQuery4:selectrange_variable[index]
Firstscore=75
Firstscore=88
Firstscore=97

studentQuery5:selectexpression
Adjustedfirstscore=82.5
Adjustedfirstscore=96.8
Adjustedfirstscore=106.7

studentQuery6:selectexpression2
Average=72.25
Average=84.5
Average=88.25

studentQuery7:selectnewanonymoustype
O'Donnell,Claire
Mortensen,Sven
Garcia,Cesar

studentQuery8:selectnewnamedtype
ID=112,Average=72.25
ID=113,Average=84.5
ID=114,Average=88.25

studentQuery9:selectresultofjoinclause
ID=114,Email=CesarGar@Contoso.com
*/


如上一个示例中的studentQuery8所示,您有时可能希望所返回序列中的元素仅包含源元素的属性子集。通过使返回的序列尽可能地小一些,可以降低内存需求,并提高查询的执行速度。通过在select子句中创建一个匿名类型,并且借助于对象初始值设定项用源元素中的适当属性对该匿名类型进行初始化,可以达到此目的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: