LINQ-查询表达式基础
一、LINQ查询的数据源
从应用程序的角度来看,原始源数据的特定类型和结构并不重要。 应用程序始终将源数据视为 IEnumerable<T> 或 IQueryable<T> 集合。
例如在 LINQ to XML 中,源数据显示为 IEnumerable
<XElement>。所以要对某个对象应用LINQ查询,该对象必须实现 IEnumerable<T> 或 IQueryable<T> 。
其中,数组类型并为实现 IEnumerable<T> 或 IQueryable<T> ,为什么也可进行LINQ查询呢?
二、查询可能会执行三种操作
- 检索元素的子集以生成新序列,而不修改各个元素。 查询然后可能以各种方式对返回的序列进行排序或分组,如下面的示例所示(假定
scores
是int[]
):
IEnumerable<int> highScoresQuery = from score in scores where score > orderby score descending select score;
- 如前面的示例所示检索元素的序列,但是将它们转换为新类型的对象。 例如,查询可以只从数据源中的某些客户记录检索姓氏。或者可以检索完整记录,然后用于构造其他内存中对象类型甚至是 XML 数据,再生成最终的结果序列。 下面的示例演示从
int
到string
的投影。 请注意highScoresQuery
的新类型。
IEnumerable<string> highScoresQuery2 =
from score in scores
where score >
orderby score descending
select $"The score is {score}";
- 检索有关源数据的单独值,如:
与特定条件匹配的元素数。
具有最大或最小值的元素。
与某个条件匹配的第一个元素,或指定元素集中特定值的总和。 例如,下面的查询从
scores
整数数组返回大于 80 的分数的数量:
int highScoreCount =
(from score in scores
where score >
select score)
.Count();
在前面的示例中,请注意在调用 Count
方法之前,在查询表达式两边使用了括号。 也可以通过使用新变量存储具体结果,来表示此行为。 这种方法更具可读性,因为它使存储查询的变量与存储结果的查询分开。
IEnumerable<int> highScoresQuery3 =
from score in scores
where score >
select score; int scoreCount = highScoresQuery3.Count();
三、查询表达式
查询表达式必须以 from 子句开头,且必须以 select 或 group 子句结尾。在第一个 from
子句与最后一个 select
或 group
子句之间,可以包含以下这些可选子句中的一个或多个:where、orderby、join、let,甚至是其他 from 子句。 还可以使用 into 关键字,使 join
或 group
子句的结果可以充当相同查询表达式中的其他查询子句的源。
下面的代码示例演示一个简单查询表达式,它具有一个数据源、一个筛选子句、一个排序子句并且不转换源元素。 该查询以 select
子句结尾。
static void Main()
{
// Data source.
int[] scores = { , , , , , }; // Query Expression.
IEnumerable<int> scoreQuery = //query variable
from score in scores //required
where score > // optional
orderby score descending // optional
select score; //must end with select or group // Execute the query to produce the results
foreach (int testScore in scoreQuery)
{
Console.WriteLine(testScore);
}
}
// Outputs: 93 90 82 82
查询变量
在上面的示例中,scoreQuery
是查询变量,它有时仅仅称为查询。查询变量可以存储采用查询语法、方法语法或是两者的组合进行表示的查询,而不是查询的结果。
开始查询表达式
查询表达式必须以 from
子句开头。 它指定数据源以及范围变量。 范围变量表示遍历源序列时,源序列中的每个连续元素。 范围变量基于数据源中元素的类型进行强类型化。 在下面的示例中,因为 countries
是 Country
对象的数组,所以范围变量也类型化为 Country
。 因为范围变量是强类型,所以可以使用点运算符访问该类型的任何可用成员。
IEnumerable<Country> countryAreaQuery =
from country in countries
where country.Area > //sq km
select country;
范围变量一直处于范围中,直到查询使用分号或 continuation 子句退出。
查询表达式可能会包含多个 from
子句。 在源序列中的每个元素本身是集合或包含集合时,可使用其他 from
子句。 例如,假设具有 Country
对象的集合,其中每个对象都包含名为 Cities
的 City
对象集合。 若要查询每个 Country
中的 City
对象,请使用两个 from
子句,如下所示:
IEnumerable<City> cityQuery =
from country in countries
from city in country.Cities
where city.Population >
select city;
结束查询表达式
查询表达式必须以 group
子句或 select
子句结尾。
group 子句
使用 group
子句可生成按指定键组织的组的序列。 键可以是任何数据类型。 例如,下面的查询会创建包含一个或多个 Country
对象并且其键是 char
值的组的序列。
var queryCountryGroups =
from country in countries
group country by country.Name[];
select 子句
使用 select
子句可生成所有其他类型的序列。 简单 select
子句只生成类型与数据源中包含的对象相同的对象的序列。 在此示例中,数据源包含 Country
对象。 orderby
子句只按新顺序对元素进行排序,而 select
子句生成重新排序的 Country
对象的序列。
IEnumerable<Country> sortedQuery =
from country in countries
orderby country.Area
select country;
select
子句可以用于将源数据转换为新类型的序列。 此转换也称为投影。 在下面的示例中,select
子句对只包含原始元素中的字段子集的匿名类型序列进行投影。 请注意,新对象使用对象初始值设定项进行初始化。
// Here var is required because the query
// produces an anonymous type.
var queryNameAndPop =
from country in countries
select new { Name = country.Name, Pop = country.Population };
使用“into”进行延续
可以在 select
或 group
子句中使用 into
关键字创建存储查询的临时标识符。 如果在分组或选择操作之后必须对查询执行其他查询操作,则可以这样做。 在下面的示例中,countries
按 1000 万范围,根据人口进行分组。 创建这些组之后,附加子句会筛选出一些组,然后按升序对组进行排序。 若要执行这些附加操作,需要由 countryGroup
表示的延续。
// percentileQuery is an IEnumerable<IGrouping<int, Country>>
var percentileQuery =
from country in countries
let percentile = (int) country.Population / 10_000_000
group country by percentile into countryGroup
where countryGroup.Key >=
orderby countryGroup.Key
select countryGroup; // grouping is an IGrouping<int, Country>
foreach (var grouping in percentileQuery)
{
Console.WriteLine(grouping.Key);
foreach (var country in grouping)
Console.WriteLine(country.Name + ":" + country.Population);
}
筛选、排序和联接
在开头 from
子句与结尾 select
或 group
子句之间,所有其他子句(where
、join
、orderby
、from
、let
)都是可选的。任何可选子句都可以在查询正文中使用零次或多次。
where 子句
使用 where
子句可基于一个或多个谓词表达式,从源数据中筛选出元素。 以下示例中的 where
子句具有一个谓词及两个条件。
IEnumerable<City> queryCityPop =
from city in cities
where city.Population < && city.Population >
select city;
orderby 子句
使用 orderby
子句可按升序或降序对结果进行排序。 还可以指定次要排序顺序。 下面的示例使用 Area
属性对 country
对象执行主要排序。 然后使用 Population
属性执行次要排序。
IEnumerable<Country> querySortedCountries =
from country in countries
orderby country.Area, country.Population descending
select country;
ascending
关键字是可选的;如果未指定任何顺序,则它是默认排序顺序。
join 子句
使用 join
子句可基于每个元素中指定的键之间的相等比较,将一个数据源中的元素与另一个数据源中的元素进行关联和/或合并。在 LINQ 中,联接操作是对元素属于不同类型的对象序列执行。 联接了两个序列之后,必须使用 select
或 group
语句指定要存储在输出序列中的元素。 还可以使用匿名类型将每组关联元素中的属性合并到输出序列的新类型中。 下面的示例关联其 Category
属性与 categories
字符串数组中一个类别匹配的 prod
对象。 筛选出其 Category
不与 categories
中的任何字符串匹配的产品。select
语句会投影其属性取自 cat
和 prod
的新类型。
var categoryQuery =
from cat in categories
join prod in products on cat equals prod.Category
select new { Category = cat, Name = prod.Name };
还可以通过使用 into 关键字将 join
操作的结果存储到临时变量中来执行分组联接。
let 子句
使用 let
子句可将表达式(如方法调用)的结果存储在新范围变量中。 在下面的示例中,范围变量 firstName
存储 Split
返回的字符串数组的第一个元素。
string[] names = { "Svetlana Omelchenko", "Claire O'Donnell", "Sven Mortensen", "Cesar Garcia" };
IEnumerable<string> queryFirstNames =
from name in names
let firstName = name.Split(' ')[]
select firstName; foreach (string s in queryFirstNames)
Console.Write(s + " ");
//Output: Svetlana Claire Sven Cesar
查询表达式中的子查询
查询子句本身可能包含查询表达式,这有时称为子查询。 每个子查询都以自己的 from
子句开头,该子句不一定指向第一个 from
子句中的相同数据源。 例如,下面的查询演示在 select 语句用于检索分组操作结果的查询表达式。
var queryGroupMax =
from student in students
group student by student.GradeLevel into studentGroup
select new
{
Level = studentGroup.Key,
HighestScore =
(from student2 in studentGroup
select student2.Scores.Average())
.Max()
};
LINQ-查询表达式基础的更多相关文章
- LINQ查询表达式基础
LINQ,语言集成查询(Language Integrated Query)是一组用C#和Visual Basic语言的扩展. 对于编写查询的开发人员来说,LINQ 最明显的"语言集成&qu ...
- LINQ查询表达式(1) - 查询表达式基础
LINQ包括五个部分:LINQto Objects.LINQ to DataSets.LINQ to SQL.LINQ to Entities.LINQ to XML. 什么是查询?它有什么用途? “ ...
- Linq专题之创建Linq查询表达式
本节我们主要介绍一下如何创建查询集合类型,关系数据库类型,DataSet对象类型和XML类型的数据源的Linq查询表达式. 下面在实例代码ReadyCollectionData()函数创建了准备的数据 ...
- 2.3 LINQ查询表达式中 使用select子句 指定目标数据
本篇讲解LINQ查询的三种形式: 查询对象 自定义查询对象某个属性 查询匿名类型结果 [1.查询结果返回集合元素] 在LINQ查询中,select子句和from子句都是必备子句.LINQ查询表达式必须 ...
- LINQ查询表达式---------let子句
LINQ查询表达式---------let子句 let子句创建一个范围变量来存储结果,变量被创建后,不能修改或把其他表达式的结果重新赋值给它.此范围变量可以再后续的LINQ子句中使用. class P ...
- LINQ查询表达式---------join子句
LINQ查询表达式---------join子句 join 子句接受两个源序列作为输入. 每个序列中的元素都必须是可以与另一个序列中的相应属性进行比较的属性,或者包含一个这样的属性. join子句使用 ...
- LINQ查询表达式---------orderby子句
LINQ查询表达式---------orderby子句 LINQ可以按元素的一个或多个属性对元素进行排序. class Program { public class PerInfo { public ...
- LINQ查询表达式---------into
LINQ查询表达式---------into into 上下文关键字创建一个临时标识符,以便将 group.join 或 select 子句的结果存储到新的标识符 class Program { pu ...
- LINQ查询表达式---------group子句
LINQ查询表达式---------group子句 LINQ表达式必须以from子句开头,以select或group子句结束.使用guoup子句来返回元素分组后的结果.group 子句返回一个 IGr ...
- LINQ查询表达式---------select子句
LINQ查询表达式---------select子句 1.1常见的select子句查询 class Program { public class PerInfo { public int Id { g ...
随机推荐
- Ubuntu系统下安装字体和切换默认字体的方法
参考链接:http://my.oschina.net/itblog/blog/278566 打开Ubuntu的软件中心,搜索:tweak,安装[Unity Tweak Tool]这款软件,如图(由于我 ...
- 高性能Javascript总结
一.加载和运行 Javascript代码执行会阻塞其他浏览器处理过程.充分利用webpack或gulp工具对文件打包压缩,减少js文件的数量,从而减少http请求的次数,以提高网页应用的实际性能. 二 ...
- MySQL检查死锁简介
- 多源最短路径floyd
#include<iostream> #define INF 105 using namespace std; int main() { ][],mark,x,y,g; while(cin ...
- atom 自定义快捷键
'atom-text-editor': 'shift-alt-i':'core:move-up' 'shift-alt-space':'core:move-down' 'shift-alt-l':'c ...
- CentOS 6.7安装(一)
CentOS 6.7安装 1.将光盘放入服务器,选择从光盘启动,选择“Install or upgrade an existing system”,并跳过光盘测试. 2.选择安装过程中使用的语言,默认 ...
- Python数据结构和类型--解压序列赋值多个变量
Python数据结构和类型 1.1 解压序列赋值给多个变量 现在有一个包含N个元素的元组或者是序列,怎样将它里面的值解压后同时赋值给N个变量? 解决思路:先通过简单的解压赋值给多个变量,前提是变量的数 ...
- Codeforces Round #273 (Div. 2)-B. Random Teams
http://codeforces.com/contest/478/problem/B B. Random Teams time limit per test 1 second memory limi ...
- ios lazying load
初步写一些自己对于lazyload的看法吧.这篇文章主要针对普通view,对于image相关的的懒加载,准备过几天研究一下在写. 懒加载,又称为延迟加载.通常用法,你有一个UITextField类型的 ...
- Mac 电源管理
在安装BatteryManager后,可以删除NullPowerMananger,AppleIntelPowerMananger, AppleIntelPowerClientMananger三个kex ...