LINQ可以对本地对象集合或远程数据源进行结构化的类型安全的查询操作。。
LINQ支持查询任何实现了IEnumerable<T>接口的集合类型,数组,列表,XML DOM,SQL Server
入门
1.查询运算符是以静态扩展方法的形式来实现的,称为标准查询运算符。
2.查询需要一个输入序列和一个运算符
3.一般查询语句是扩展方法和Lambda结合使用。这种叫流式语法。
4.查询语法 from a in name...
流式语法
1.流式语法是最基础也是最灵活的编写LINQ表达式的方式,流式语法是扩展方法的完美展现
2.也可以调用普通的静态方法来代替扩展方法(编译器最终会帮我们将扩展方法转化成普通的静态方法)
3.Lambda表达式中的逻辑,每一个元素都会执行一次
4.不用Lambda使用传统的委托和匿名方法也是可以的
5.LINQ的某些对顺序的操作是基于原始排序的
查询表达式
1.查询表达式一般以from字句开始,最后一select或者group字句结尾。from字句的作用是声明范围变量,通过from,可以遍历序列元素。
2.编译器最终会将查询表达式转化成流式语法,意味着,任何能够用查询表达式的地方都能够用流式语法表示。
3.范围变量:紧跟在from关键字后面的标志符称为范围变量。范围变量值当前序列中即将进行操作的元素。不同子句的范围变量枚举的序列都是不同的(可能被筛选过了,可能被排序过了)
4.查询语法在引入新范围变量时更好,在引入外部范围变量时更好。流式语法中包含了一些查询语法没有的关键字,此时使用流式语法。
5.使用混合语法,包含了流式语法和查询语法,有时可以出奇效
延迟执行
1.大部分查询运算符的一个重要特性是并非在构造时执行,而是在枚举时执行。以下运算符除外
1.1返回单个元素或标量元素,First,Count
1.2转换运算符,ToArray,ToList等
2.当重复枚举时,延迟执行的查询也会重复执行。在数据库中,执行相同的操作时,会反复的查询数据库,此时可以将其转化为ToList,然后枚举这个List就可以了。
3.查询语句中Lambda在捕获外部变量时的表现和一般情况下一样(延迟)
4.延迟执行的原理是采用了装饰器模式
子查询
1.子查询就是在Lambda中包含另外一个查询。
2.子查询也是延迟查询的。
3.子查询是从外部向内查询的,枚举时,每一次外部查询都会进行一次内部查询
4.当子查询的结果是固定时,使用子查询是浪费效率的,因为每一次循环都会进行一次子查询。所以可以把子查询拿出来,获得值,然后将值放入查询中。这样,实际上子查询只进行了一次。然而,这种情况已经不叫子查询了,是分开的2次查询。
5.子查询中的First和Count是不会导致外部查询立即执行的。
构造方式
1.渐进式构造:可以先执行一次where,然后再执行where
2.into关键字:触发继续查询;触发GroupJoin
3.into可以在映射之后继续执行后续查询,可以作为渐进式查询的快捷途径。
4.into关键字只能出现在select和group字句之后
5.into最终也会转变成流式语法
6.into关键字后面的查询语句不能够使用之前定义的范围变量
7.查询的包装。可以对查询的结果进行包装
from in
(
from in
select
)
where
select
映射方式
1.select不仅可以select(a=>a.Name)还可以select(a=>new {a.Name,a.Age}),也可以Select(a=>new Person{Name=a.Name})
还可以Select(a=>new {Name=a.Name})
2.let关键字可以在查询中定义一个新的变量,这个变量能够和范围变量并存
3.let定义的变量不但包含范围变量,还包含了新的表达式。不像into无法使用范围变量
4.可以使用多个let
解释型查询
解释性查询是用来操作数据库的。
本地查询都是对实现了IEnumerable<T>的类型进行操作,而解释型查询是对IQueryable<T>进行操作。
解释性查询会在运行时解释,并生成表达式树。
LINQ to SQL和EF是两种IQueryable<T>的实现
解释型查询的工作机制
1.IQueryable和IEumnerable都包含where等方法,我们在求某一个值的where方法时,需要决定使用哪一个where。如果是本地类型,肯定是IEumnerable的where方法。如果是远程类型,比如Table<T>、DbSet<T>,都继承了IQueryable和IEumnerable,在具体使用时,会使用IQueryable的where方法,最终翻译成表达式树,而不是IEumnerable中的委托。
2.解释型查询也是延迟查询,进行2次枚举就会进行2次查询数据库
3.本地查询是链式的,可以一个查询接着一个查询,而解释型查询是一次性的。
综合使用解释型查询和本地查询
简单来说,就是数据库查一次就够了,然后获得的数据进行本地化查询。
可以使用一些方法将IQueryable转化为IEumnerable,比如ToList()等等或者IEumnerable有的而IQueryable没有的。
LINQ to SQL和Entity Framework
1.LINQ to SQL的实体类:属性[Table]表示表,[Column]表示列等等
2.EF的实体类:可以像1中的定义属性,还要定义数据库和实体类之间的映射关系,不像1中一个类对应一张表,在EF中,一张表可以对多个类,一个类也可以对应多张表。
3.DataContect和ObjectContext和DbContext差不对。提供链接字符串,追踪数据库,作为一个生产查询对象的工厂。
构建查询表达式
1.Enumerable接受委托,Queryable接受表达式树
2.Compile可以将表达式树转换成委托
3.AsQueryable将一个本地序列包装为Queryable,后续的查询运算符解析为表达式树。
4.表达式树:每一个符号都是一种表达式