参考书籍《Illustrated C#7, 5th Edition》
什么是LINQ?
- LINQ = Language Integrated Query 发音"link"
- LINQ是.NET框架的扩展。用类似SQL语法查询数据库一样,来查询数据集。SQL查询数据库,database。LINQ查询数据集,data collection
原因是SQL查询规范的表格,也即数据库,而LINQ不一定是规范的数据。SQL查询的是数据库,而LINQ查询可以查程序数据集。
- 第二点补充,使用LINQ可以查询database(数据库),对象集合(object collection),XML文档(XML document)等
第一个例子:
using System;
using System.Collections.Generic; //集合
using System.Linq;//LINQ
class Program
{
static void Main()
{
int[] numbers = { 2, 12, 5, 15 }; // Data source 数据源
IEnumerable<int> lowNums = // Define and store the query. 定义数据data &存储查询query
from n in numbers
where n < 10
select n;
foreach (var x in lowNums) // Execute the query.执行查询
Console.Write($"{ x }, ");
}
}
结果:
LINQ Providers
翻译过来是LINQ 提供程序,但是总感觉这个怪怪的
在之前的示例中,数据源是int数组。它是程序在内存中的对象。
但是LINQ还可以查询各种数据,SQL数据库(database),XML 文档(XML document)等
对于每一种数据,都有对应的LINQ 查询模块,这些代码模块叫做LINQ providers
所以:LINQ providers 可以理解为 代码模块 code modules
- 微软为常见数据源类型(common data source types)提供了LINQ providers
- 可以使用任何支持LINQ的语言(这里是C#),来查询数据源(有LINQ providers提供的data)
- 第三方不断提供针对各种数据源类型的LINQ providers
Method Syntax and Query Syntax
Method 语法 和 Query语法
结论:微软推荐Query语法,但是有时候Method语法也不得不用。
class Program
{
static void Main()
{
int[] numbers = { 2, 5, 28, 31, 17, 16, 42 };
var numsQuery = from n in numbers // Query syntax 查询语法
where n < 20
select n;
var numsMethod = numbers.Where(N => N < 20); // Method syntax 方法语法
int numsCount = (from n in numbers // Combined 混合
where n < 20
select 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);
}
}
这里var numsQuery = from n in numbers // Query syntax 查询语法
where n < 20
select n;
本来应该是这样写的:
Enumerable<int> numsQuery = from n in numbers // Returns an enumerator,返回枚举器
where n < 20
select n;
用var来推断,比较简洁。
来看看教程怎么说:
- 第一个语句,创建了一个int数组,用三个值进行初始化
- 第二个语句,创建了一个LINQ查询,它可以用来枚举查询结果。
- 第三个语句,执行查询后,调用LINQ本身的一个方法Count来返回结果数量。
第二个语句和第三个语句左边的变量叫做"查询变量"(query variable),类型分别是IEnumerable<int>和int
但是可以用var简化,用编译器来推断。(compiler infer the types of the query variables)
注意,第二个语句中,并没有真正执行查询,lowNums查询变量也不包含查询的结果。直到处理枚举的时候,才会执行查询。
查询变量numsCount那个是int变量,而且是真实的整数值,这个值只能是查询后结果用count返回的数字,所以是执行了查询的,这个是重大区别。
- 如果查询表达式返回的是枚举变量,则查询一直到处理枚举的时候才会执行
- 如果枚举被处理多次,查询就会执行多次。
- 如果在进行遍历后,查询执行之前数据有改动,则查询会使用新的数据
- 如果查询表达式返回的是标量scalar(也即普通变量),查询会立即执行,并把结果保存在查询变量中。
var query = from item in arr1
where item < 13
select item;
与SQL语法区别的地方是这个select放在后面的。
SQL的join,联结
Join一下:
var query = from s in students
join c in studentsInCourses on s.StID equals c.StID
using System;
using System.Linq;
class Program
{
// Declare classes.
public class Student
{
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 students
join c in studentsInCourses on s.StID equals c.StID
where 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 }");
}
}
结果:
From 子句
From…let…where
Let子句