using System.Linq; LINQ学习
https://zhidao.baidu.com/question/200851857.html
1.LINQ 概述
LINQ(Language-Integrated Query,语言集成查询)是微软在.NET Framework 3.5版本引入的新功能,它能够将查询功能直接引入.Net Framework所支持的编程语言中。
根据上图显示,vs2010和以后版本应该是支持的,我这边2015不支持,2019可以
如图所示,LINQ主要由LINQ to Objects、LINQ to ADO.NET、LINQ to XML三部分组成。其中:
LINQ to Objects:可以查询是实现了Ienumerable或Ienumerable<T>的集合,即任意可枚举的集合。
LINQ to ADO.NET:
LINQ to SQL:可查询基于关系型数据库的数据,并进行CRUD等操作。
LINQ to DataSet:对DataSet对象进行检索/过滤/排序等操作。
LINQ to XML:可对XML结构数据进行查询或操作。
2.LINQ查询基础
2.1 查询形式
- Method syntax 方法语法
通过方法调用的形式调用LINQ查询,这些方法是一组命令式的,标准查询运算符形式的方法,并如SQL语句那样指明调用顺序。
1 2 3 | string[] testStrs = new String[] { "This", "is", "my", "home" }; List< string > splitList = testStrs.Where(x => x.Length == 2).ToList(); foreach (string v in splitList) Console.Write(v + "\t"); |
输出:is my
- Query syntax 查询语法
查询语法是声明式的,类似SQL语句的查询子句,编译器会将其翻译成方法调用的形式。
1 2 3 | string[] testStrs = new String[] { "This", "is", "my", "home" }; var splitList = from str in testStrs where str.Length == 2 select str; foreach (object v in splitList) Console.Write(v + "\t"); |
输出:is my
2.2 查询表达式
LINQ查询表达式有一个或者多个LINQ查询子句按照一定的规则组成,其中查询子句包括:
from ... in:指定数据源和范围变量,这里的范围变量指数据源中的每一个元素
where:筛选条件
select:指定查询结果的类型和表现形式
orderby:对查询结果进行排序(降序/升序)
group ... by:对查询结果进行分组
into:引用join、group和select子句的结果
join ... on:连接多个查询操作的数据源
let:引入用于存储查询表达式中子表达式结果的范围变量,这里的范围变量指局部变量
LINQ查询表达式必须包括from子句,并且以from子句开头。下面是一个完整的例子:
1 2 3 4 5 6 7 8 9 | List< Scores > scores = GetScores(); List< Student > students = GetStudents(); var list = from stu in students join score in scores on stu.ID equals score.StudentID let sum = score.Chinese + score.Math + score.English //定义临时变量sum where sum / 3 > 60 group stu by new { stu.Age } into result orderby result.Key.Age descending select new { Age = result.Key.Age, Count = result.Count() }; |
2.3 标准查询运算符
LINQ标准查询运算符是有一系列API方法组成,并支持查询任何数组或集合对象。其中,被查询的集合必须实现IEnumberable<T>接口。常用的标准查询运算符(查询方法)有:
Select:同select子句
Where:同where子句
Take:指定要获取的元素个数,同SQL中的top语句
Skip:跳过指定的元素个数开始获取
Join:对两个对象执行内连接
GroupBy:同group by子句
OrderBy/ThenBy:OrderBy同orderby子句,ThenBy可对更多的元素进行排序
Count:返回集合中元素的个数
Sum:返回集合中某一项值得总和
Min:返回元素中最小的值
Max:返回元素中最大的值
下面是一个完整的例子:
1 2 3 4 5 6 7 8 9 10 11 | List< Scores > scores = new List< Scores >(); List< Student > students = new List< Student >(); var JoinData = students.Join(scores, //内连接数据源 stu => stu.ID, //内连接外键 score => score.StudentID, //内连接主键 (stu, score) => new { Student = stu, Scores = score }); //指定查询结果 var ResultList = JoinData.Where( W => W.Scores.Chinese > 60) .GroupBy(G => G.Student.Age) .OrderByDescending(O => O.Key) //OrderBy默认为升序,OrderByDescending降序 .Select(S => new { Age = S.Key, Count = S.Count()}); |
2.4 LINQ语言特性
隐式类型: var关键字声明变量,编译器通过变量所赋的值来推导数据类型,考虑到可读性,尽量显示指明数据类型。
匿名类型:通过var关键字和new关键字实现创建一个匿名类型,例:var obj = new { Name = "大宝哥" };
对象初始化器:结合前面两个特性,例:var stu = new Student(){ Name = "大宝哥" };
2.5 Func委托与匿名方法
Func是一个泛型委托,为了方便理解可以将其当做方法的数据类型,通过参数来区分。由于是泛型委托,其参数及返回值由开发者自行决定,注意输入参数可以有0~16个。
1 2 3 | int GetSum(int a, int b) { return a + b; } //定义一个求和方法 Func< int , int, int> sum = GetSum; //声明并初始化一个Func委托 int result = sum(2, 3); //调用Func委托 |
这边查看定义的Func委托sum说明,可以看出声明类型中Func<int,int,int>的3个int参数,前两个泛型参数为调用方法GetSum中的参数类型,最后一个泛型参数为GetSum方法的返回值。
对于上面的显式声明的委托及调用方法,还可以通过前面说的匿名方法来定义委托的回调方法。
1 2 3 4 | Func< int , int, int> sum = delegate (int a, int b) { retrun a +b; } |
2.6 Lambda表达式
Lambda表达式是在Func泛型委托和匿名方法的基础上,再进一步对代码进行简化,将委托的回调方法简化到只有参数列表和方法体。“=>”符号左边为表达式的参数列表,右边为方法体,参数列表可包含0到多个参数,声明方式和所要调用的方法形参格式一样。例如,将2.5示例方法中的delegate关键字舍去,可以简化为
1 | Func< int , int, int> sum = (int a, int b) => { retrun a +b; } |
若只有一个参数的情况,可以省去参数列表两边的括号
1 | Func< int , int> sum = a => { retrun a * 2; } |
注意,若没有参数的情况,需要保留一个空的括号来表示
1 | Func< int , int> sum = () => { retrun 3 * 2; } |
3. LINQ实际应用
LINQ本质上就是对数据集合的查询,不论是List、Dictionary等IEnumerable集合,还是XML、DB等,都需要先连接到数据源。这边单独讲下LINQ to SQL,其他的大同小异不做阐述。
3.1 新建LINQ to SQL类
若在Visual Studio中没有找到“LINQ to SQL 类”,则在VS的“工具”菜单中,选择“获取工具和功能”打开Visual Studio Installer
在“单个组件”选项下找到并勾选“LINQ to SQL 工具”后,点击“修改”
继续前面新建LINQ to SQL类的操作,选择“LINQ to SQL类”并创建后,会在项目下生成一个dbml文件
到这一步就要执行连接数据库的操作了,连接DB的操作过程这边不做阐述。
连接完成后打开dbml文件,将所需操作的数据库表拖动至dbml文件页面空白处,这边就会生成实例化操作数据库的上下文Context类,同EF一样通过Context类获取并操作数据。
1 2 | CityDataContext cdc = new CityDataContext(); var findResult = cdc.City.Where( c => c.Name.Equals( "Shanghai" )); |
这边要注意的是对象关系设计器(O/R设计器)仅支持用于 SQL Server 的.NET Framework 数据提供程序 (System.Data.SqlClient),途中用了MySQL数据库,将左边数据库表拖放至dbml文件中时出现错误。
若不想更改数据库的话,建议使用其他对数据库数据操作的方式,如ODBC,EF等获取数据源后再进行LINQ操作。
3.2 LINQ数据分页查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | /// <summary> /// 获取页数据方法 /// </summary> /// <param name="index">要获取的页码</param> /// <param name="pageSize">每页数据条目数</param> public void GetPageData( int index, int pageSize) { CityDataContext cdc = new CityDataContext(); var findResult = cdc.City.Where( c => c.Name.Length > 3); //获取数据源并筛选结果 //根据传入分页信息参数计算需要跳过的数据条数 int skip = (index - 1) * pageSize; //跳过计算后的数据条数并获取要获取的数据条数 var pageResult = findResult.Skip(skip).Take(pageSize); //显示数据操作...... } |
System.Linq 命名空间提供支持使用语言集成查询 (LINQ) 进行查询的类和接口。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战