语言集成查询(Language Integrated Query,简称 LINQ)是 C# 最强大的特性之一。它允许开发人员直接在 C# 语言中编写查询语句,以便对来自不同数据源(如集合、数据库、XML 文档等)的数据进行操作和查询。LINQ 通过提供一种统一且可读性强的方式来查询和转换数据,让处理数据变得更加容易。
本篇博客将逐步引导你了解 LINQ 的基础知识,从语法开始,再到更高级的主题,都会以通俗易懂的方式进行讲解。
在深入探讨语法之前,让我们先来了解一下 LINQ 为何如此重要:
在开始编写 LINQ 查询之前,让我们先来了解一些基本概念。
让我们从一个简单的示例开始。假设我们有一个整数列表,并且想要找出其中所有的偶数。
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// 数据源
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// LINQ 查询
var evenNumbers = from num in numbers
where num % 2 == 0
select num;
// 执行
foreach (var num in evenNumbers)
{
Console.WriteLine(num);
}
}
}
解释:
numbers
就是我们的数据源,它是一个整数列表。from
关键字开头,后面跟着 where
和 select
子句。
from num in numbers
:遍历 numbers
列表中的每一项。where num % 2 == 0
:筛选出能被 2 整除的数字(即偶数)。select num
:选择符合条件的数字。当你运行这段代码时,它将输出:
2
4
6
8
10
LINQ 提供了两种语法类型:
示例:
var evenNumbers = from num in numbers
where num % 2 == 0
select num;
var evenNumbers = numbers.Where(num => num % 2 == 0);
这两种语法是等效的,你可以根据自己觉得哪种更具可读性来选择使用。
LINQ 提供了丰富的操作符来操作数据。以下是一些最常用的操作符:
Where
:基于某个条件对元素进行筛选。var evenNumbers = numbers.Where(num => num % 2 == 0);
Select
:将一个序列中的每个元素投影为新的形式。var squares = numbers.Select(num => num * num);
OrderBy
/ OrderByDescending
:按升序或降序对元素进行排序。var sortedNumbers = numbers.OrderBy(num => num);
GroupBy
:根据共同的属性对元素进行分组。var groupedNumbers = numbers.GroupBy(num => num % 2);
Join
:基于某个键将两个序列进行连接。var joinedData = from num in numbers
join num2 in otherNumbers on num equals num2
select new { num, num2 };
Aggregate
:对序列中的每个元素执行一个操作,并返回单个结果。var sum = numbers.Aggregate((a, b) => a + b);
LINQ 并不局限于集合,它还可以查询各种数据源,例如:
var result = from num in numbers where num > 5 select num;
var query = from p in context.Products where p.Price > 100 select p;
var xmlQuery = from x in xmlDoc.Elements("Book") where (string)x.Element("Author") == "AuthorName" select x;
var xmlQuery = from x in xmlDoc.Elements("Book") where (string)x.Element("Author") == "AuthorName" select x;
LINQ 中的一个重要概念是延迟执行。LINQ 查询在定义时并不会执行,而是在对其进行迭代(例如使用 foreach
循环)时才会执行,这被称为延迟执行。
var query = from num in numbers where num > 5 select num;
// 此处查询并未执行
foreach (var num in query)
{
Console.WriteLine(num); // 在此处查询才执行
}
当调用像 ToList()
、ToArray()
、First()
或 Count()
等方法时,会立即执行查询,这就是立即执行。
var immediateExecution = numbers.Where(num => num > 5).ToList(); // 立即执行
var results = from num in numbers
select new { Number = num, Square = num * num };
Let
关键字:允许你将子查询的结果存储在一个变量中,以便在同一个查询内重复使用。var result = from num in numbers
let square = num * num
where square > 10
select square;
Join
:用于基于一个公共键合并多个数据源。var joinResult = from p in products
join c in categories on p.CategoryId equals c.Id
select new { p.Name, c.CategoryName };
GroupJoin
:合并数据并对结果进行分组。var groupJoin = from c in categories
join p in products on c.Id equals p.CategoryId into productGroup
select new { c.CategoryName, Products = productGroup };
Cross Join
:将一个数据源的每个元素与另一个数据源的每个元素进行组合。var crossJoin = from p in products
from c in categories
select new { p.Name, c.CategoryName };
Zip
:通过根据元素位置合并两个序列的元素来将它们进行组合。var zipped = numbers.Zip(otherNumbers, (first, second) => first + second);
LINQ 是 C# 中一个强大的工具,它让处理数据变得更加直观且具有可读性。无论你是查询集合、数据库还是 XML,LINQ 都提供了一种统一的方式来处理数据。通过理解并掌握 LINQ,你可以编写更高效、更易于维护且更简洁的代码。