Linq
Linq
1、查询表达式
-
查询表达式是一种使用查询语法的表达式,它用于查询和转换来自任意支持Linq的数据源中的数据。
-
查询表达式使用许多常见的c#语言构造,易读简介,容易掌握。
-
它是由一组类似的sql或XQuery的声明性语法编写的字句组成。每个字句可以包含一个或多个C#表达式,这些表达式本身也可能是查询表达式或包含查询的表达式。
-
查询表达式结构
- 以from子句开头
- 中间可以包括一个或多个where子句、let子句、join子句、orderby子句和group子句,甚至还可以是from子句。
- 以select或者group子句结束
-
各个字句介绍
-
from:制定查询操作的数据源和范围变量。
-
select:制定查询结果的类型和表现形式。
-
where:筛选元素的逻辑条件。
-
let:引入用来临时保存查询表达式中的子表达式结果的范围变量。
-
orderby:对查询结果进行排序操作,包括升序以及降序。
-
group :查询结果进行分组
-
into:提供一个临时标识符。join子句、group子句或者select子句可以通过该标识符引用查询操作中的中间结果。
-
join:链接多个用于查询操作的数据源 equals 以及on
int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // 简单查询 var arrQuery1 = from a in arr select a; // 带条件的简单查询 var arrQuery2 = from a in arr where a < 5 select a; var arrNew = arrQuery1.ToArray<int>(); // 关联查询 int[] arr2 = new int[] { 11, 22, 33, 4, 45, 66, 87, 8, 90 }; var arrQuery3 = from a in arr from b in arr2 where a == b select a; // 带计算的查询 var arrQuery4 = from a in arr select a * 10; // 查询后获取一个新对象 var arrQuery5 = from a in arr select new { // 匿名对象 id = a, name = $"title-{a}" }; // 两个条件,不是用and或者or 而是用 && || var arrQuery6 = from a in arr where a >= 3 && a <= 6 select a; var arrQuery7 = from a in arr where a >= 9 || a <= 3 select a; // 带函数的查询 var arrQuery8 = from a in arr where isEven(a) select a; // 偶数判断 static bool isEven(int a) { return a%2 == 0; } // let 子句 创建一个范围变量来存储结果 var arrQuery9 = from a in arr let b = a % 2 == 0 where b select a; var arrQuery10 = from a in arr let b = a % 2 where b == 0 select a; var arrQuery11 = from a in arr let b = a % 2 select b; // orderby 子句,默认是升序ascending,降序用descending var arrQuery12 = from a in arr2 orderby a select a; var arrQuery12 = from a in arr2 orderby a descending select a; // 分组和排序 var arrQuery13 = from a in arr where a > 1 && a < 9 orderby a descending group a by a % 2; foreach (var item in arrQuery13) { foreach (var num in item) { Console.WriteLine(num); } Console.WriteLine("-----分组-----"); } // into 语法 var arrQuery14 = from a in arr where a > 1 && a < 9 orderby a descending group a by a % 2 into g from n in g // 临时标识符,存储数据 select n; foreach (var item in arrQuery14) { Console.WriteLine(item); } // join 用法 equals 效果等同于前面的arrQuery3 var arrQuery15 = from a in arr join b in arr2 on a equals b select a;
-
2、Linq
Linq初级语法
// 复杂的分组与遍历
string[] strs = new string[] { "java", "C", "C++", "PASCAL", "FORTRAN", "LISP", "Prolog", "CLIPS", "OpenCyc", "Fazzy", "Python", "PHP", "Ruby", "Lua", "True basic", "Qbasic", "Virtual Basic" };
var arrQuery16 = from a in strs
group a by a.Length into g
orderby g.Key
select g;
foreach (var item in arrQuery16)
{
foreach (var row in item)
{
Console.WriteLine($"{item.Key}={row}");
}
}
ar arrQuery17 = from a in strs
group a by a.Length into g
orderby g.Key
select new
{
key = g.Key,
num = g.Count()
};
foreach (var item in arrQuery17)
{
Console.WriteLine(item.ToString());
}
协变与逆变
- msdn解释:
- 协变:能够使用与原始制定的派生类型相比,派生程度更大的类型。
- 逆变:则指的是能够使用比派生程度更小的类型。
- 协变(out:输出参数):很自然的变化,比如string →object
- 逆变(in:输入参数):不正常的变化,比如object→string
- 泛型参数标记为out,标明它是用来输出的,作为结果返回
- 泛型参数标记为in,标明它是用来输入的,只能作为参数
class Animal
{
}
class Dog : Animal
{
}
Dog dog=new Dog();
Animal animal = dog; // 这种可以直接协变
List<Dog> dogs = new List<Dog> ();
List<Animal> animals = new List<Animal> ();
// animals = dogs; // 报错
animals = dogs.Select (dog => dog as Animal ).ToList ();
// 下面这种就可以,因为 public interface IEnumerable<out T> : IEnumerable
IEnumerable<Dog> someDogs = new List<Dog>();
IEnumerable<Animal> somAnimals = someDogs;
// 协变 public interface IEnumerable<out T> : IEnumerable
IEnumerable<Dog> someDogs = new List<Dog>();
IEnumerable<Animal> somAnimals = someDogs; // 强制转换为合法
// 逆变 public delegate void Action<in T>(T obj);
Action<Animal> animals = new Action<Animal>(a=>{ /* 动物叫的方法*/ });
Action<Dog> dogs = animals;
dogs(new Dog());
软件与数据间的问题
- 任何软件都有代码和数据组成,任何开发都要与数据打交道
- 在对象数据与数据库之间进行沟通经常会有一道坎
- 是否能够简化程序与数据之间的沟通方式
Linq
- Language Integrated Query 语言集成式查询
- Linq将编程语言与数据的世界连接在一起
- Linq实现了统一的数据访问方案
Linq构成
- 查询运算符
- 查询表达式
- 表达式树
- Linq的dll以及命名空间
查询运算符
分类 | 分类 | ||
---|---|---|---|
过滤 | where、ofType | 设置 | Distinct 、except、Intersect 、Union |
投射 | select、selectMany | 转换 | AsEnumerable、AsQueryable、Cast、ToArray、ToList、ToDictionary |
分段 | Skip、SkipWhile、Take、TakeWhile | 相等 | SequenceEqual |
排序 | OrderBy、OrderByDescending、ThenBy、ThenByDescending、Reverse | 元素 | ElementAt、ElementAtOrDefault、First、FirstOrDefault、Last、LastOrDefault、Single、SingleOrDefault |
拼接 | Concat | 生成 | DefaultEmpty、Empty、Range、Repeat |
联结 | Join、GroupJoin | 量词 | All、Any、Contains |
分组 | GroupBy、ToLookup | 聚合 | Aggregate、Average、Count、LongCount、Max、Min、Sum |
-
过滤
- Where - Where查询;延迟
- OfType - 过滤集合中的指定类型;延迟
-
设置
- Distinct - 过滤集合中的相同项;延迟
- Except - 从某集合中删除其与另一个集合中相同的项;延迟
- Intersect - 获取不同集合的相同项(交集);延迟
- Union - 连接不同集合,自动过滤相同项;延迟
-
投射
- Select - Select选择;延迟
- selectMany- Select选择(一对多);延迟
-
转换
- Cast - 将集合转换为强类型集合;延迟
- ToArray - 将集合转换为数组;不延迟
- ToList - 将集合转换为List
集合;不延迟 - ToDictionary - 将集合转换为<K, V>集合;不延迟
-
分组
- Skip - 跳过集合的前n个元素;延迟
- Take - 获取集合的前n个元素;延迟
- SkipWhile - 直到某一条件成立就停止跳过;延迟
- TakeWhile - 直到某一条件成立就停止获取;延迟
-
相等
- SequenceEqual - 判断两个集合是否相同;不延迟·
-
排序
- OrderBy - 按指定表达式对集合正序排序;延迟
- ·OrderByDescending - 按指定表达式对集合倒序排序;延迟
- ThenBy
- ThenByDescending
- Reverse - 对集合反向排序;延迟
-
元素
- ElementAt - 返回集合中指定索引的元素;不延迟
- ElementAtOrDefault - 返回集合中指定索引的元素(如果没有则返回默认值);不延迟
- First 返回集合中的第一个元素;不延迟
- FirstOrDefault - 返回集合中的第一个元素(如果没有则返回默认值);不延迟
- Last - 返回集合中的最后一个元素;不延迟
- LastOrDefault- 返回集合中的最后一个元素(如果没有则返回默认值)
- Single- 根据表达式返回集合中的某一元素;不延迟
- SingleOrDefault - 根据表达式返回集合中的某一元素(如果没有则返回默认值);不延迟
-
拼接
- ·Concat - 连接不同集合,不会自动过滤相同项;延迟
-
生成
- DefaultEmpty - 查询结果为空则返回默认值;延迟
- Empty
- Range
- epeat
-
联结
- Join - Join查询;延迟
- GroupJoin - 分组Join查询;延迟
-
l量词
- All- 判断集合中是否所有元素都满足某一条件;不延迟
- Any - 判断集合中是否有元素满足某一条件;不延迟
- Contains - 判断集合中是否包含有某一元素;不延迟
-
分组
- GroupBy- 分组;延迟
- ToLookup
-
聚合
- Aggregate - 根据输入的表达式获取一个聚合值;不延迟
- Average- 集合应为数字类型集合,求其平均值;不延迟
- Count- 返回集合中的元素个数,返回int;不延迟
- LongCount - 返回集合中的元素个数,返回long;不延迟
- Max- 返回集合的最大值;不延迟
- Min - 返回集合的最小值;不延迟
- Sum - 集合应为数字类型集合,求其和;不延迟
世界上没有什么事情是跑步解决不了的,如果有,那就再跑一会!