LINQ
LINQ是c#3.0的核心,平常工作中经常使用到,但不明白其中的原理,那现在就来讲讲LINQ:
- LINQ的简介
- 查询和查询表达式
- LinqToSQL
LINQ的简介
LINQ(Language Integrated Query)语言集成查询是一组用于c#和Visual Basic语言的扩展。它允许编写C#或者Visual Basic代码以查询数据库相同的方式操作内存数据。—— [ 百度百科 ]
顾名思义,LINQ是关于查询的,其目的是使用一致的语法和特性,以一种易阅读、可组合的方式,使对多数据源的查询变得简单。
查询和查询表达式
查询基础
查询是一组指令,描述要从给定数据源(或源)检索的数据以及返回的数据应具有的形状和组织。 查询与它生成的结果不同。
通常情况下,源数据按逻辑方式组织为相同类型的元素的序列。 例如,SQL 数据库表包含行的序列。 在 XML 文件中,存在 XML 元素的“序列”(尽管这些元素在树结构按层次结构进行组织)。 内存中集合包含对象的序列。
从应用程序的角度来看,原始源数据的特定类型和结构并不重要。 应用程序始终将源数据视为 IEnumerable<T>或者IQueryable<T>集合。
查询表达式基础
查询表达式是以查询语法表示的查询。 查询表达式是一流的语言构造。 它如同任何其他表达式一样,可以在 C# 表达式有效的任何上下文中使用。 查询表达式由一组用类似于 SQL 或 XQuery 的声明性语法所编写的子句组成。 每个子句进而包含一个或多个 C# 表达式,而这些表达式可能本身是查询表达式或包含查询表达式。
查询表达式必须以 from 子句开头,且必须以 select 或 group 子句结尾。 在第一个 from 子句与最后一个 select 或 group 子句之间,可以包含以下这些可选子句中的一个或多个:where、orderby、join、let,甚至是其他 from 子句。 还可以使用 into 关键字,使 join 或 group 子句的结果可以充当相同查询表达式中的其他查询子句的源。
点标记
什么是点标记,就是Linq表达式和Lambda表达式相关的整条语句,在微软并没有给出官方的命名,在《深入理解C#》中被称为点标记。具体格式如下。
//查询表达式
var students1 = from t in db.Students
where t.Name == "张三"
select new { t.Id, t.Name, t.Age };
//点标记
var students2 = db.Students
.Where(t => t.Name == "张三")
.Select(t => new { t.Id, t.Name, t.Age });
Lambda表达式是什么呢,可以通过lambda表达式操作符=>来轻松识别。lambda表达式可在编译器预计会看到一个委托的地方使用(什么是委托呢可以看我之前的文章委托的总结)。编译器看到这个lambda表达式之后会在类中自动定义一个新的私有方法。这个新方法称为匿名函数。上述这个Where(t => t.Name == “张三”)中t为委托方法中的传参是Student类型的,t.Name == “张三”为委托方法的返回结果,可以看到返回的是一个布尔值,而where方法正好需要一个FunC<Student,bool>的委托方法,而Select(t => new { t.Id, t.Name, t.Age })中需要一个FunC<Student,Student>的委托方法。如果不需要传入参数就用()=>就好了,如果需要两个传入参数就(x,y)=>,其它同理。
下面这个就是查询出一个数组中第三大的数字,
//查询表达式
IEnumerable<int> result = (from i in data orderby i descending select i).Distinct().Take(3);
//点标记
IEnumerable<int> result = data.OrderByDescending(a => a).Distinct().Take(3);
//在这个以降序排序的含有三个元素的数组中选择最后一个
Console.WriteLine(result.Last());
本文主要参考了《深入理解C#(第2版)》、《CLR via c#》,在此表达诚挚的敬意