LINQ(Language Integrated Query,语言集成查询)是C#中一项革命性特性,它将数据查询能力直接集成到编程语言中,支持对集合(内存数据)、数据库(如Entity Framework)、XML、JSON等多种数据源进行统一风格的查询与操作。通过强类型的编译时检查、直观的语法(方法链或查询表达式)以及丰富的操作符,LINQ大幅简化了数据处理的代码复杂度。
![图片[1]_C#中的LINQ:简化数据查询与操作用法详解_知途无界](https://zhituwujie.com/wp-content/uploads/2025/11/d2b5ca33bd20251121085145.png)
一、LINQ的核心优势
- 统一语法:无论操作对象是数组、列表、数据库表还是XML文档,均可使用相似的语法结构。
- 强类型安全:编译时检查查询逻辑,避免运行时因字段名拼写错误等问题。
- 延迟执行(Deferred Execution):多数LINQ查询(如
Where、Select)在实际枚举结果(如调用ToList())时才执行,提升性能。 - 丰富的操作符:提供过滤、排序、分组、聚合等常用数据操作的一站式支持。
二、LINQ的两种使用方式
1. 查询表达式语法(Query Expression Syntax)
类似SQL的声明式语法,适合复杂的查询逻辑(如多条件、嵌套查询)。
关键字:from、where、select、orderby、group、join等。
2. 方法链语法(Method Syntax)
通过扩展方法(如Where()、Select())以链式调用实现,更灵活且支持Lambda表达式。
常用方法:Where(predicate)、Select(projector)、OrderBy(keySelector)、GroupBy(keySelector)等。
提示:两种语法可混合使用,编译器最终都会转换为方法调用。
三、基础用法示例(以集合数据为例)
场景:对一个List<Student>集合进行查询与操作
1. 准备数据模型
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public double Score { get; set; }
public string Class { get; set; }
}
// 示例数据
List<Student> students = new List<Student>
{
new Student { Id = 1, Name = "张三", Age = 20, Score = 85.5, Class = "A班" },
new Student { Id = 2, Name = "李四", Age = 22, Score = 92.0, Class = "B班" },
new Student { Id = 3, Name = "王五", Age = 20, Score = 78.0, Class = "A班" },
new Student { Id = 4, Name = "赵六", Age = 21, Score = 88.5, Class = "B班" }
};
2. 常用查询操作
(1)过滤(Where)
需求:筛选年龄大于20的学生。
方法链语法:
var result = students.Where(s => s.Age > 20);
// 输出:李四(22), 赵六(21)
foreach (var s in result)
{
Console.WriteLine($"{s.Name}({s.Age})");
}
查询表达式语法:
var result = from s in students
where s.Age > 20
select s;
(2)排序(OrderBy/OrderByDescending)
需求:按分数降序排列所有学生。
方法链语法:
var result = students.OrderByDescending(s => s.Score);
// 输出:李四(92.0), 赵六(88.5), 张三(85.5), 王五(78.0)
(3)投影(Select)
需求:只获取学生的姓名和分数。
方法链语法:
var result = students.Select(s => new { s.Name, s.Score });
// 输出:{ Name = 张三, Score = 85.5 }, { Name = 李四, Score = 92.0 }...
查询表达式语法:
var result = from s in students
select new { s.Name, s.Score };
(4)分页(Skip + Take)
需求:获取第2页数据(每页2条,跳过第1页)。
方法链语法:
int pageSize = 2, pageNumber = 2;
var result = students.OrderBy(s => s.Id)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
// 输出:王五(第3条), 赵六(第4条)
3. 聚合操作
(1)计数(Count)
需求:统计A班的学生人数。
int aClassCount = students.Count(s => s.Class == "A班"); // 输出:2
(2)求和(Sum)、平均值(Average)、最大值(Max)、最小值(Min)
需求:计算所有学生的平均分数。
double avgScore = students.Average(s => s.Score); // 输出:86.0
4. 分组(GroupBy)
需求:按班级分组,统计每班人数及平均分。
方法链语法:
var groupResult = students.GroupBy(s => s.Class)
.Select(g => new
{
ClassName = g.Key,
Count = g.Count(),
AvgScore = g.Average(s => s.Score)
});
/* 输出:
A班: 人数=2, 平均分=81.75
B班: 人数=2, 平均分=90.25
*/
查询表达式语法:
var groupResult = from s in students
group s by s.Class into g
select new
{
ClassName = g.Key,
Count = g.Count(),
AvgScore = g.Average(s => s.Score)
};
5. 连接查询(Join)
场景扩展:假设有一个List<Teacher>集合,关联学生与教师(通过班级)。
方法链语法:
List<Teacher> teachers = new List<Teacher>
{
new Teacher { Class = "A班", Name = "陈老师" },
new Teacher { Class = "B班", Name = "刘老师" }
};
var joinResult = students.Join(
teachers,
s => s.Class, // 学生表的关联键
t => t.Class, // 教师表的关联键
(s, t) => new { s.Name, TeacherName = t.Name } // 合并结果
);
/* 输出:张三(陈老师), 王五(陈老师), 李四(刘老师), 赵六(刘老师) */
四、LINQ的延迟执行与立即执行
- 延迟执行:
Where、Select、GroupBy等操作不会立即执行查询,而是在实际枚举结果时(如调用foreach、ToList())才触发。var query = students.Where(s => s.Age > 20); // 此时未执行查询 students.Add(new Student { Id = 5, Age = 23 }); // 动态添加数据 var result = query.ToList(); // 执行时包含新添加的数据 - 立即执行:
ToList()、ToArray()、First()、Single()等方法会立即触发查询并缓存结果。var firstStudent = students.First(s => s.Age > 20); // 立即执行,返回第一个符合条件的对象
五、LINQ to Entities(数据库查询)
当使用Entity Framework(EF Core)时,LINQ查询会被转换为SQL语句,直接操作数据库。
示例(查询年龄大于20的学生):
using (var db = new MyDbContext())
{
// 方法链语法(推荐)
var dbResult = db.Students.Where(s => s.Age > 20).ToList();
// 查询表达式语法
var dbResult2 = (from s in db.Students
where s.Age > 20
select s).ToList();
}
注意:EF Core中的LINQ操作会生成优化的SQL,避免将全表数据加载到内存再过滤。
六、总结:何时使用LINQ?
- 推荐场景:处理集合数据(如
List<T>、数组)、需要链式组合多个操作(过滤+排序+投影)、追求代码简洁性与可读性。 - 替代方案:对于极高性能要求的场景(如遍历百万级数据且仅需简单过滤),直接使用
for循环可能更高效(但牺牲可读性)。
通过灵活运用LINQ,开发者可以以更少的代码实现复杂的数据操作,同时保持类型安全与可维护性。掌握LINQ是C#开发者处理数据的核心技能之一!
























暂无评论内容