欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#之LINQ

程序员文章站 2022-07-09 18:50:42
出来工作学习的越来越多了,对C#也是理解越来越深,总是想找个时间总结一下自己学过的东西,文字记录,经常翻看,查缺补漏的让自己不至于变得善忘,遂就有了此系列,权当复习巩固之用。 一、概述 1.什么是Linq? 不管我们进行什么项目的开发,跟数据打交道绝对是绕不过去的,有了数据,我们难免要去操作数据,大 ......

出来工作学习的越来越多了,对c#也是理解越来越深,总是想找个时间总结一下自己学过的东西,文字记录,经常翻看,查缺补漏的让自己不至于变得善忘,遂就有了此系列,权当复习巩固之用。

一、概述

1.什么是linq?

不管我们进行什么项目的开发,跟数据打交道绝对是绕不过去的,有了数据,我们难免要去操作数据,大量的数据给我们带来了操作的麻烦,.net为了解决这个问题,在 .net framework 3.5 版中引入的一项创新功能,它在对象领域和数据领域之间架起了一座桥梁,它就是linq(language integrated quary)。

2.哪些对象能使用linq?

在 c# 中可为以下对象编写 linq 查询:sql server 数据库、xml 文档、ado.net 数据集以及支持 ienumerable 或泛型 ienumerable 接口的任何对象集合。但是使用的linq项目的framework 必须是3.5及以上的。
C#之LINQ

二.常见标准查询运算符

1.select

此方法将序列中的每个元素投影到新表单。
例:C#之LINQ

2.where

此方法基于谓词筛选值序列。
我们可以对数据进行筛选

	var query = table.where(x => x.name == "tom");

同时也提供了按序号进行筛选,index从0开始

	var query = table.where((x, index)=> index >= start && index <= end);

3.first()、firstordefault()、last()和lastordefault()

与where()类似,但不同的是first()只会返回满足条件的第一个序列元素,若是元素不存在时,first()会抛出异常,firstordefault()则是会返回元素的默认值。
last()、lastordefault()与first()、firstordefault()正好相反,它们返回序列中符合条 件的最后一个元素,若是元素不存在时,last()会抛出异常,lastordefault()则是会返回元素的默认值

int[] array = {1, 2, 3, 4};
int item = array.first(x=>x%2 == 0);//2
int item = array.firstordefault(x=>x == 5);//0
int item = array.last();//4
int item =  array.lastordefault();//4

4.single()和singleordefault()

single()与first()类似。但是single()要求序列中有且只有一个满足条件的项,否则抛出异常,singleordefault()在无满足条件项时,返回默认值。

int[] array = {1, 2};
int item = array.single();//抛出异常

5.distinct()

大都数人一看到这个词就知道他的用法,distinct()用于提出序列中重复的数据,并返回其余的所有数据。如:

int[] array = {2,2,3,3,4,4,5,5};
var query = array.distinct();//[2,3,4,5]

6.cast()

cast用于将非泛型序列转换为泛型序列 ienumerable。当某一序列项无法成功转换时,则会抛出异常

arraylist list = new arraylist();
list.add(1);
list.add("二");
var query=list.cast<int>();//异常:  system.invalidcastexception: 指定的转换无效

7.groupby()

跟在sql中作用一致,groupby()就是用作分组的。
groupby()返回了一个ienumerable<igrouping<tkey,tsource>>的借口类型,我们查看接口可知,这个,igrouping<tkey,tsource>也是一个序列,只是多了一个key属性,并且依据 key进行了分组。

8.intersect()和except()

intersect()返回两个序列中相同元素构成的序列,如:

int[] array1 = { 2,3,4,5};
int[] array2 = {2,3,6,7};
var query = array1.intersect(array2);//2,3

except(),则是返回第一个序列中有而第二个序列中没有的数据,如:

int[] array1 = { 2,3,4,5};
int[] array2 = {2,3,6,7};
var query = array1.except(array2);//4,5

9.orderby()、thenby()、orderbydescending()和thenbydescending()

orderyby与orderbydescending()很好理解,一个是升序一个是降序排列。如:

var query = table.orderby(x=>x.time);//对时间进行升序排列
var querydesc = table.orderbydescending(x=>x.time);//对时间进行降序排列

那么thenby()与thenbydescending是干嘛用的呢?当我们需要一个较为复杂的排序,先按时间进行排序,再按名字进行排序,那么我们此时就要用到这两个方法了。因为thenby()是在iorderedenumerable上定义的扩展方法,因此不能直接在ienumrable上调用,而在这四个排序方法返回的都是iorderedenumerable,故可以在后面直接调用。

10.take()、takewhile()、skip()和skipwhile()

take()方法返回原序列中的前n个元素构成的新序列,如:

var query = table.take(3);//取前3个元素

takewhile()会取出连续满足条件的数据,直到遇到第一个不满足的数据。
skip()则是跳过前n个元素,如:

var query = table.skip(3);//跳过前三个返回后面的数据

skipwhile() 会一直跳过连续满足条件的数据,直到遇到第一个不满足的数据就返回该元素之后的所有元素构成的序列。
take()与skip()这两个运算符在linq to sql 中常用作分页。如:

var query = table.skip(10).take(10);//每页10条数据,显示第二页数据

11.zip()

zip()对两个序列中位置相同的两个元素进行操作,基于两个元素的操作结果返回一个新 的元素。如果两个序列的长度不相等,则以长度短的为准。如:

int[] array1 = { 1, 2, 3, 4, 5 }; 
string[] array2 = { "星期一", "星期二", "星期三" }; 
var query = array1.zip(array2, (x,y) => string.format("{0},{1}", x, y));
返回结果为:
1,星期一 
2,星期二 
,星期三

12.concat()和union()

concat()运算符用于连接两个序列。如:

int[] array1 = { 3, 1, 2 };
int[] array2 = { 2, 3, 5 };
var query = array1.concat(array2);//  3,1,2,2,3,5

union()运算符也用于连接两个序列,但是会剔除相同的项目。如:

int[] array1 = { 3, 1, 2 };
int[] array2 = { 2, 3, 5 };
var query = array1.union(array2);//  3,1,2,5

13.contains()、any()

contains()判断某一个元素是否存在于序列中,any()则是判断序列中是否存在满足表达式的元素,两者返回的都是bool,满足则返回true。

总结

linq在我们需要操作数据的代码中应用频繁,它具有延迟加载的概念,只有在数据上调用聚合函数时才会执行查询操作,对我们很多操作都提供了极大地便利。学好linq在ef等orm框架中也能更快速的开发。
本文借鉴了张子阳老师的《net之美》第五章linq的部分内容,在此表示感谢。