LINQ查询表达式(1) - 查询表达式基础
LINQ包括五个部分:LINQto Objects、LINQ to DataSets、LINQ to SQL、LINQ to Entities、LINQ to XML。
什么是查询?它有什么用途?
“查询”是指一组指令,这些指令描述要从一个或多个给定数据源检索的数据以及返回的数据应该使用的格式和组织形式。 查询不同于它所产生的结果。
通常,源数据会在逻辑上组织为相同种类的元素序列。 SQL 数据库表包含一个行序列。 与此类似,ADO.NET DataTable 包含一个 DataRow 对象序列。 在 XML 文件中,有一个 XML 元素“序列”(不过这些元素按分层形式组织为树结构)。 内存中的集合包含一个对象序列。
从应用程序的角度来看,原始源数据的具体类型和结构并不重要。 应用程序始终将源数据视为一个 IEnumerable<T> 或 IQueryable<T> 集合。 在 LINQ to XML 中,源数据显示为一个 IEnumerable<XElement>。 在 LINQ to DataSet 中,它是一个 IEnumerable<DataRow>。 在 LINQ to SQL 中,它是您定义用来表示 SQL 表中数据的任何自定义对象的 IEnumerable 或 IQueryable。
查询结果3种:
- 检索元素子集,产生新的序列,不修改单个元素,可以对其进行分组、排序
IEnumerable<int> highScoresQuery =
from score in scores
where score >
orderby score descending
select score;
- 检索元素子集,转换元素类型
IEnumerable<string> highScoresQuery2 =
from score in scores
where score >
orderby score descending
select String.Format("The score is {0}", score);
- 检索有关源数据的单一值
int highScoreCount =
(from score in scores
where score >
select score)
.Count(); -or- IEnumerable<int> highScoresQuery3 =
from score in scores
where score >
select score; int scoreCount = highScoresQuery3.Count();
什么是查询表达式
“查询表达式”是用查询语法表示的查询,它像其它表达式一样,可以应用于任何C#表达式有效的上下文中。
查询表达式由一组用类似于 SQL 或 XQuery 的声明性语法编写的子句组成。 每个子句又包含一个或多个 C# 表达式,而这些表达式本身又可能是查询表达式或包含查询表达式。
查询表达式必须以 from 子句开头,并且必须以 select 或 group 子句结尾。 在第一个 from 子句和最后一个 select 或 group 子句之间,查询表达式可以包含一个或多个下列可选子句:where、orderby、join、let 甚至附加的 from 子句。 还可以使用 into 关键字使 join 或 group 子句的结果能够充当同一查询表达式中附加查询子句的源。
- 查询变量
存储查询本身,而非结果的变量,LINQ规范中,变量命名常以query结尾。
查询变量可以显示或隐式声明,使用隐式声明用 var 关键字指示编译器在编译时推断查询变量的类型。
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
上例中,查询变量并不存储实际的结果数据(这些数据是在 foreach
循环中产生的),另外,当 foreach
语句执行时,查询结果并不是通过查询变量 scoreQuery
返回的。 相反,它们是通过迭代变量 testScore
返回的。 可以在另一个 foreach
循环中迭代 scoreQuery
变量。 只要该变量和数据源都没有修改,该变量都将产生相同的结果。
查询变量可以存储用查询语法或方法语法(或二者的组合)表示的查询,如下:
// Query syntax
IEnumerable<City> queryMajorCities =
from city in cities
where city.Population >
select city; // Method-based syntax
IEnumerable<City> queryMajorCities2 = cities.Where(c => c.Population > );
- 开始查询表达式(from)
查询表达式必须以 from 子句开头。 它同时指定了数据源和范围变量。 在对源序列进行遍历的过程中,范围变量表示源序列中的每个后续元素。 将根据数据源中元素的类型对范围变量进行强类型化。 在下面的示例中,因为 countries 是 Country 对象数组,所以范围变量也被类型化为 Country, 这样就可以使用点运算符来访问该类型的任何可用成员。
IEnumerable<Country> countryAreaQuery =
from country in countries
where country.Area > //sq km
select country;
在使用分号或延续子句退出查询之前,范围变量将一直位于范围中。
查询表达式可以包含多个 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;
- 结束查询表达式(select 或 group)
查询表达式必须以 select
子句或 group
子句结尾。
select 子句
使用 select 子句可产生所有其他类型的序列。 简单的 select 子句只是产生与数据源中包含的对象具有相同类型的对象的序列。
在此示例中,数据源包含 Country 对象。 orderby 子句只是将元素重新排序,而 select 子句则产生重新排序的 Country 对象的序列。
IEnumerable<Country> sortedQuery =
from country in countries
orderby country.Area
select country;
可以使用 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 };
group 子句
使用 group 子句可产生按照指定的键组织的组序列, 键可以采用任何数据类型。 例如,下面的查询创建一个组序列,该序列包含一个或多个 Country 对象,并且它的键是 char 值。
var queryCountryGroups =
from country in countries
group country by country.Name[]; //country.name[0] is char type.
使用“into”进行延续
可以在 select 或 group 子句中使用 into 关键字来创建用于存储查询的临时标识符。 当您必须在分组或选择操作之后对查询执行附加查询操作时,需要这样做。
在下面的示例中,以一千万人口范围为界对 countries 进行分组。 在创建这些组之后,使用附加子句筛选掉某些组,然后按升序对剩下的组进行排序。 若要执行这些附加操作,需要使用由 countryGroup 表示的延续。
// percentileQuery is an IEnumerable<IGrouping<int, Country>>
var percentileQuery =
from country in countries
let percentile = (int) country.Population /
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);
}
- 筛选、排序和连接……(where、orderby、join……)
在 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;
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 };
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(new char[] { ' ' })[]
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()
};
参考
[1] MSDN,LINQ查询表达式
[2] 维基百科,LINQ语言集成查询
LINQ查询表达式(1) - 查询表达式基础的更多相关文章
- lambda表达式和查询表达式
(1)Lambda表达式定义: Lambda是创建匿名函数的另一种形式.它比对应的匿名方法更加的简化.因此,所有的情况都推荐使用Lambda表达式. 它可以包括表达式和语句,并且用于创建委托和事件 ...
- 编写高质量代码改善C#程序的157个建议——建议27:在查询中使用Lambda表达式
建议27:在查询中使用Lambda表达式 LINQ实际上是基于扩展方法和Lambda表达式的.任何LINQ查询都能通过扩展方法的方式来代替. var personWithCompanyList = f ...
- Asp.net Core C#进行筛选、过滤、使用PredicateBuilder进行动态拼接lamdba表达式树并用作条件精准查询,模糊查询
在asp.net core.asp.net 中做where条件过滤筛选的时候写的长而繁琐不利于维护,用PredicateBuilder进行筛选.过滤.LInq配合Ef.core进行动态拼接lamdba ...
- Thinkphp查询 1.查询方式 2.表达式查询 3.快捷查询 4.区间查询 5.组合查询 6.统计查询 7.动态查询 8.SQL 查询
1.使用字符串作为条件查询 $user = M('User'); var_dump($user->where('id=1 AND user="蜡笔小新"')->sele ...
- SqlSugar常用查询实例-拉姆达表达式
SqlSugar支持拉姆达表达式查询,匿名对象参数等,相对还是比较方便好用的. 一.查询列表: //查询列表 SqlSugarClient db = SugarContext.GetInstance( ...
- Thinkphp中查询复杂sql查询表达式,如何表达MYSQL中的某字段不为空is not null?
Thinkphp中查询复杂sql查询表达式,如何表达MYSQL中的某字段不为空is not null?先上两种实现方式的实例:$querys["house_type_image"] ...
- ORDER BY 子句在视 图、内联函数、派生表、子查询和公用表表达式中无效
SQL语句: select * from (select distinct t2.issue,cashmoney from (select distinct issue from lot_gamepa ...
- [sql Server]除非另外还指定了TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效
今天遇到一个奇怪的问题,项目突然要从mysql切换到sql server数据库,包含order by 子句的嵌套子查询报错. 示例:select top 10 name,age,sex from ( ...
- Linq表达式、Lambda表达式你更喜欢哪个?
什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...
- LINQ中的一些查询语句格式
LINQ的基本格式如下所示:var <变量> = from <项目> in <数据源> where <表达式> orderby <表达式> ...
随机推荐
- 基于Mac的Appium环境搭建(java)
一.jdk安装 1.下载地址 http://www.oracle.com/technetwork/java/javase/downloads/index.html 2.安装 3.配置环境变量: ope ...
- 【转】Lombok介绍、使用方法和总结
链接:http://www.yuanrengu.com/index.php/20180324.html 1 Lombok背景介绍 官方介绍如下: Project Lombok makes java a ...
- python学习-69 包装和授权
包装 1.二次加工标准类型(包装) class List(list): def append(self, a_objcet): if type(a_objcet) is str: super().ap ...
- 一个长耗时SQL在TiDB和Mysql上的耗时测试
之前看到的TiDB和MySql的性能对比都是大量短耗时请求下的压测,单机情况下TiDB和MySql的确有些差距,不过笔者最近碰到的场景更多是sql要扫描的行数不小的情况下单sql比较耗时的问题,所以自 ...
- java之结合代码理解synchronized关键字
为了保证数据的一致性即实现线程的安全性,java虚拟机提供了同步和锁机制.synchronized关键字是最基本的互斥同步手段.除此之外,还可以使用java.util.concurrent包中的重入锁 ...
- linux ubuntu-16.04-配置java1.8和Tomcat8
前言 第一次使用linux ubuntu16.04 服务器,所以做一下常用配置的记录. JDK 1.创建存放jdk的目录 一般在usr/local下创建一个java文件夹 cd /usr/local ...
- H5调起IOS原生商店支付
参考文档:http://www.html5plus.org/doc/zh_cn/payment.html 申请内购项目摘自 https://www.jianshu.com/p/1e79bfbe46e2 ...
- Qt 添加程序图标和系统托盘图标
添加程序图标 第一种方法: 1.创建程序的时候,选择添加默认图标 2.替换程序目录下的ico文件,编译生成即可. 第二种方法: 比较适合一开始没有添加程序图标的情况 1.项目右键-->添加--& ...
- iOS pushViewController 和 presentViewController的区别 详解
pushViewController 导航控制器入栈的方式切换页面presentViewController 模态切换的方式切换页面 1:用 UINavigationController 的时候用 p ...
- SAP开源的持续集成-持续交付的解决方案
SAP开源的持续集成/持续交付的解决方案: (1) 一个叫做piper的github项目,包含一个针对Jenkins的共享库和一个方便大家快速搭建CI/CD环境的Docker镜像: (2) 一套SAP ...