当前位置: 首页 > news >正文

第20章 LINQ 笔记

第20章 LINQ

20.1 什么是LINQ

LINQ代表语言集成查询(Language Integrated Query)

LINQ是.NET框架的扩展,允许使用SQL查询数据库的方式类查询数据集合

static void Main()
{int[] numbers = { 2, 12, 5, 15 }; // Data sourceIEnumerable<int> lowNums = // Define and store the query.from n in numberswhere n < 10select n;foreach (var x in lowNums) // Execute the query.Console. Write($"{ x }, ");
}// output
2, 5,

20.2 LINQ提供程序

对于每一种数据源类型,有对应的LINQ查询的代码模块,叫做LINQ提供程序。

LINQ的体系结构,支持LINQ的语言以及LINQ提供程序
在这里插入图片描述

匿名类型

匿名类型常用于LINQ查询的结果中

创建匿名类型的变量,使用new关键字、对象初始化语句

new { FieldProp = InitExpr, FieldProp = InitExpr, ...}

具体示例

static void Main( )
{var student = new {Name="Mary Jones", Age=19, Major="History"};// Must use var Anonymous object initializerConsole.WriteLine($"{ student.Name }, Age { student.Age }, Major: { student.Major}");
}// output
Mary Jones, Age 19, Major: History

主要事项:

匿名类型只能用于局部变量,不能用于类成员

匿名类型使用var关键字作为变量类型

匿名类型创建的属性是只读的

对象初始化语句

// 赋值形式、成员访问表达式、标识符形式
var student = new { Age = 19, Other.Name, Major };

示例

class Other
{static public string Name = "Mary Jones";
}
class Program
{static void Main(){string Major = "History";Assignment form Identifiervar student = new { Age = 19, Other.Name, Major};Member accessConsole.WriteLine($"{student.Name }, Age {student.Age }, Major: {student.Major}");}
}// output
Mary Jones, Age 19, Major: History

如果编译器遇到另一个具有相同参数名、推断类型、顺序的匿名类型对象初始化语句,会重用这个类型直接创建新的实例,不会创建新的匿名类型。

20.3 方法语法和查询语法

方法语法 使用标准的方法调用,命令式的,指明了查询方法调用的顺序

查询语法 使用查询表达式书写,是声明式的查询想要返回的东西

微软推荐使用查询语法,更易读、更清晰地标名查询意图,更不容易出错

static void Main( )
{int[] numbers = { 2, 5, 28, 31, 17, 16, 42 };var numsQuery = from n in numbers // Query syntaxwhere n < 20select n;var numsMethod = numbers.Where(N => N < 20); // Method syntaxint numsCount = (from n in numbers // Combinedwhere n < 20select n).Count();foreach (var x in numsQuery)Console.Write($"{ x }, ");Console.WriteLine();foreach (var x in numsMethod)Console.Write($"{ x }, ");Console.WriteLine();Console.WriteLine(numsCount);
}// output
2, 5, 17, 16,
2, 5, 17, 16,
4

20.4 查询变量

查询可以返回两种类型的结果:

枚举数据 是满足查询参数的项列表

标量 是满足查询条件的结果的某种摘要形式

int[] numbers = { 2, 5, 28 };
// 枚举器
IEnumerable<int> lowNums = from n in numbers // Returns an enumeratorwhere n < 20select n;// 返回项的总和
int numsCount = (from n in numbers // Returns an intwhere n < 20select n).Count();

20.5 查询表达式的结构

查询表达式由from子句和查询主体组成

子句必须按照一定顺序出现

from子句和select group子句两部分是必需的

其他子句可选的

select子句在表达式最后

可以有任意多的from let where 子句
在这里插入图片描述

20.5.1 from子句

from子句指定了要作为数据源使用的数据集合

迭代遍历逐个表示数据源的每一个元素

from子句语法

Type 是集合中元素的类型,可选的,编译器可以从结合中推断类型

Item 迭代遍历的名字

Items 查询集合的名字

from Type Item in Items
int[] arr1 = {10, 11, 12, 13};
// Iteration variable
var query = from item in arr1where item < 13 // Uses the iteration variableselect item; // Uses the iteration variable
foreach( var item in query )Console.Write( $ "{ item },");// output
10, 11, 12

20.5.2 join子句

使用联结来结合两个或更多集合中的数据

联结操作接受两个集合,创建一个临时的对象集合,其中每个对象包含两个原始集合对象中所有的字段

联结语法

// 使用equals 关键字
join Identifier in Collection2 on Field1 equals Field2

示例

var query = from s in studentsjoin c in studentsInCourses on s.StID equals c.StID

20.5.3 什么是联结

LINQ中的Join接受两个集合,创建一个新的集合,其中每一个元素包含两个原始集合中的元素成员。

class Program
{public class Student { // Declare classes.public int StID;public string LastName;}public class CourseStudent {public string CourseName;public int StID;}static Student[] students = new Student[] {new Student { StID = 1, LastName = "Carson" },new Student { StID = 2, LastName = "Klassen" },new Student { StID = 3, LastName = "Fleming" },};// Initialize arrays.static CourseStudent[] studentsInCourses = new CourseStudent[] {new CourseStudent { CourseName = "Art", StID = 1 },new CourseStudent { CourseName = "Art", StID = 2 },new CourseStudent { CourseName = "History", StID = 1 },new CourseStudent { CourseName = "History", StID = 3 },new CourseStudent { CourseName = "Physics", StID = 3 },};static void Main( ){// Find the last names of the students taking history.var query = from s in studentsjoin c in studentsInCourses on s.StID equals c.StIDwhere c.CourseName == "History"select s.LastName;// Display the names of the students taking history.foreach (var q in query)Console.WriteLine($"Student taking History: { q }");}
}//output
Student taking History: Carson
Student taking History: Fleming

20.5.4 查询主体中的from…let…where片段

from…let…where是查询主体的第一部分,可选的,由任意数量的3种子句构成:from子句、let子句、where子句
在这里插入图片描述

1.from子句

查询表达式必需从from子句开始,后面是查询主体

static void Main()
{var groupA = new[] { 3, 4, 5, 6 };var groupB = new[] { 6, 7, 8, 9 };var someInts = from a in groupA // Required first from clausefrom b in groupB // First clause of query bodywhere a > 4 && b <= 8select new {a, b, sum = a + b}; // Object of anonymous typeforeach (var x in someInts)Console.WriteLine(x);
}// output
{ a = 5, b = 6, sum = 11 }
{ a = 5, b = 7, sum = 12 }
{ a = 5, b = 8, sum = 13 }
{ a = 6, b = 6, sum = 12 }
{ a = 6, b = 7, sum = 13 }
{ a = 6, b = 8, sum = 14 }

2.let子句

接受一个表达式的运算符,并把它赋值给一个需要在其他运算符种使用的标识符

static void Main()
{var groupA = new[] { 3, 4, 5, 6 };var groupB = new[] { 6, 7, 8, 9 };var someInts = from a in groupAfrom b in groupBlet sum = a + b // Store result in new variable.where sum == 12select new {a, b, sum};foreach (var a in someInts)Console.WriteLine(a);
}// output
{ a = 3, b = 9, sum = 12 }
{ a = 4, b = 8, sum = 12 }
{ a = 5, b = 7, sum = 12 }
{ a = 6, b = 6, sum = 12 }

3.where子句

where子句根据运算表达式,来去除不符合指定条件的项

static void Main()
{var groupA = new[] { 3, 4, 5, 6 };var groupB = new[] { 6, 7, 8, 9 };var someInts = from int a in groupAfrom int b in groupBlet sum = a + bwhere sum >= 11 // Condition 1where a == 4 // Condition 2select new {a, b, sum};foreach (var a in someInts)Console.WriteLine(a);
}// output
{ a = 4, b = 7, sum = 11 }
{ a = 4, b = 8, sum = 12 }
{ a = 4, b = 9, sum = 13 }

20.5.5 orderby子句

orderby子句接受一个表达式,并根据表达式按顺序返回结果项

排序方向:ascending 升序(默认)、descending 降序

可以有任意多个子句,必须使用逗号分隔

static void Main( ) {var students = new [] // Array of objects of an anonymous type{new { LName="Jones", FName="Mary", Age=19, Major="History" },new { LName="Smith", FName="Bob", Age=20, Major="CompSci" },new { LName="Fleming", FName="Carol", Age=21, Major="History" }};var query = from student in studentsorderby student.Age // Order by Age.select student;foreach (var s in query) {Console.WriteLine($"{ s.LName }, { s.FName }: { s.Age }, { s.Major }");}
}// output
Jones, Mary: 19, History
Smith, Bob: 20, CompSci
Fleming, Carol: 21, History

20.5.6 select…group子句

由两种类型的子句组成:select子句、group…by子句

select子句指定要选择所选对象的哪些部分,可以是以下任意一项:

整个数据项

数据项的一个字段

数据项中几个字段组成的新对象

group…by子句 可选的,用来指定选择的项如何被分组。

select Expression
group Expression1 by Expression2

示例 - 使用select子句选择整个数据项

using System;
using System.Linq;
class Program {static void Main() {var students = new[] // Array of objects of an anonymous type{new { LName="Jones", FName="Mary", Age=19, Major="History" },new { LName="Smith", FName="Bob", Age=20, Major="CompSci" },new { LName="Fleming", FName="Carol", Age=21, Major="History" }};var query = from s in studentsselect s;foreach (var q in query)Console.WriteLine($"{ q.LName }, { q.FName }: { q.Age }, { q.Major }");}
}// output
Jones, Mary: 19, History
Smith, Bob: 20, CompSci
Fleming, Carol: 21, History

示例 - 使用select子句选择对象的某些字段

var query = from s in studentsselect s.LName;
foreach (var q in query)Console.WriteLine(q);// output
Jones
Smith
Fleming

20.5.7 查询中的匿名类型

查询结果可以由原始集合的项、原始集合中项的字段或匿名类型组成

select子句 用大括号包围的字段,使用逗号分隔 来创建匿名类型

select new { s.LastName, s.FirstName, s.Major };

示例

using System;
using System.Linq;
class Program
{static void Main(){var students = new[] // Array of objects of an anonymous type{new { LName="Jones", FName="Mary", Age=19, Major="History" },new { LName="Smith", FName="Bob", Age=20, Major="CompSci" },new { LName="Fleming", FName="Carol", Age=21, Major="History" }};var query = from s in studentsselect new { s.LName, s.FName, s.Major };foreach (var q in query)Console.WriteLine($"{ q.FName } { q.LName } -- { q.Major}");} 
}//output
Mary Jones -- History
Bob Smith -- CompSci
Carol Fleming -- History

20.5.8 group子句

group子句根据指定的标准,对选择的对象进行分组

作为分组依据的属性叫做键

返回 已经形成项的分组的可枚举类型

语法示例

group student by student.Major;

示例-根据学生主修课程进行分组

static void Main( )
{var students = new[] // Array of objects of an anonymous type{new { LName="Jones", FName="Mary", Age=19, Major="History" },new { LName="Smith", FName="Bob", Age=20, Major="CompSci" },new { LName="Fleming", FName="Carol", Age=21, Major="History" }};var query = from student in studentsgroup student by student.Major;foreach (var g in query) // Enumerate the groups.{Console.WriteLine("{0}", g.Key);foreach (var s in g) // Enumerate the items in the group.Console.WriteLine($" { s.LName }, { s.FName }");}
}// output
HistoryJones, MaryFleming, Carol
CompSciSmith, Bob

20.5.9 查询延续:into子句

查询延续子句可以接受查询的一部分的结果并赋予一个名字,可以在查询的另一个部分中使用
在这里插入图片描述

示例 查询联结了groupA和groupB,并将结果命名未groupAandB

static void Main()
{var groupA = new[] { 3, 4, 5, 6 };var groupB = new[] { 4, 5, 6, 7 };var someInts = from a in groupAjoin b in groupB on a equals binto groupAandB // Query continuation from c in groupAandBselect c;foreach (var v in someInts)Console.Write($"{ v } ");
}

20.6 标准查询运算符

20.6.1 标准查询运算符的签名
20.6.2 查询表达式和标准查询运算符
20.6.3 将委托作为参数
20.6.4 LINQ预定义的委托类型
20.6.5 使用委托参数的示例
20.6.6 使用Lambda表达式参数的示例

20.7 LINQ to XML

20.7.1 标记语言
20.7.2 XML基础
20.7.3 XML类
20.7.4 使用XML特性
20.7.5 其他类型的节点
20.7.6 使用LINQ toXML的LINQ查询

http://www.xdnf.cn/news/1301059.html

相关文章:

  • 8.15网络编程——UDP和TCP并发服务器
  • 【数据分享】上市公司创新韧性数据(2007-2023)
  • 数据驱动测试提升自动化效率
  • 终极手撸cpu系列-详解底层原理-CPU硬核解剖:从0和1到 看透CPU逻辑设计内部原理,弄清楚现代多线程cpu工作原理
  • Microsoft Visual Studio常用快捷键和Windows系统常用快捷键的整理
  • Linux-地址空间
  • 开发避坑指南(27):Vue3中高效安全修改列表元素属性的方法
  • 【学习笔记】NTP服务客户端配置
  • Go语言中安全停止Goroutine的三种方法及设计哲学
  • 前瞻性技术驱动,枫清科技助力制造企业借助大模型完成生产力转化
  • zabbix部署问题后常见问题
  • 新手入门Makefile:FPGA项目实战教程(二)
  • 【CV 目标检测】②R-CNN模型
  • 【Redis】分布式系统的演化过程
  • MyBatis的基本用法和配置方式
  • Highcharts Dashboards | 打造企业级数据仪表板:从图表到数据驾驶舱
  • 全球电商业财一体化:让出海品牌实现“看得见的增长“
  • demo 通讯录 + 城市选择器 (字母索引左右联动 ListItemGroup+AlphabetIndexer)笔记
  • Nginx反向代理与缓存实现
  • 人工智能与社会治理:从工具到生态的范式重构
  • Kafka生产者——提高生产者吞吐量
  • 切换VSCODE 中的默认 shell
  • GitHub 上 Star 数量前 18 的开源 AI Agent 项目
  • 制造装配、仓储搬运、快递装卸皆适配!MinkTec 弯曲形变传感器助力,让人体工学改变劳动生活
  • Vue3从入门到精通: 4.5 数据持久化与同步策略深度解析
  • Elasticsearch 深分页问题
  • 计算图的力量:从 PyTorch 动态图到 TensorFlow 静态图的全景与实战
  • Nginx蜘蛛请求智能分流:精准识别爬虫并转发SEO渲染服务
  • 【Java EE进阶 --- SpringBoot】初识Spring(创建SpringBoot项目)
  • iceberg 底层存储HDFS与juiceFS的区别