LINQ的基本语法包含如下的8个上下文关键字,这些关键字和具体的说明如下
出于工作需要,准备把LINQ的相关知识梳理一遍,希望能填补下之前学习漏掉的或是没有注意的地方,也为未来减轻压力~
LINQ查询表达式的基本语法很容易掌握,它使用C#常见的语言构造,从外观上看,和我们常用的SQL类似,并且查询表达式中的变量可以用匿名类型,所以在很多情况下,不需要指定变量类型就可以构建LINQ表达式。
LINQ的数据源可以是数据库对象或是XML流等,也可以使实现了IEnumerable或者泛型IEnumberable<T>接口的集合对象。
LINQ的基本语法包含如下的8个上下文关键字,这些关键字和具体的说明如下:
关键字 | 说明 |
from | 指定范围变量和数据源 |
where | 根据bool表达式从数据源中筛选数据 |
select | 指定查询结果中的元素所具有的类型或表现形式 |
group | 对查询结果按照键值进行分组(IGrouping<TKey,TElement>) |
into | 提供一个标识符,它可以充当对join、group或select子句结果的引用 |
orderby | 对查询出的元素进行排序(ascending/descending) |
join | 按照两个指定匹配条件来Equals连接两个数据源 |
let | 产生一个用于存储查询表达式中的子表达式查询结果的范围变量 |
下面依此总结这8个关键字的常用查询语句写法。
1.from子句
如果要写一个LINQ表达式,就必须是以from子句开头。个人觉得from子句中需要注意的地方就是多个from子句的书写。

- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Collections;
- namespace LINQ
- {
- /// <summary>
- /// LINQ,重点是感悟from子句中的查询变量的灵活
- /// </summary>
- class Program
- {
- static void Main(string[] args)
- {
- //1单个form子句
- string[] values = { "LINQ学习","LINQ基本语句","from子句","单个from子句"};
- var value = from v in values
- where v.IndexOf("LINQ") > -1
- select new { v, v.Length };
- foreach (var n in value)
- {
- Console.WriteLine("{0},{1}",n.v,n.Length );
- }
- Console.ReadKey(false);
- //2使用LINQ查询ArrayList
- ArrayList gList = new ArrayList();
- gList.Add(new GustInfo { Name="DebugLZQ", Age=26, Tel="88888888"});
- gList.Add(new GustInfo { Name="博客园",Age=6, Tel ="666666"});
- gList.Add(new GustInfo { Name = "M&MSoft", Age =9, Tel = "55555" });
- var query = from GustInfo gust in gList
- where gust.Age > 9
- select gust;//范围变量gust制定了数据类型
- foreach (GustInfo g in query)
- {
- Console.WriteLine("{0} 年龄:{1} 电话:{2}",g.Name,g.Age,g.Tel );
- }
- Console.ReadKey(false);
- //3复合from子句
- List<GustInfo2> gList2 = new List<GustInfo2>()
- {
- new GustInfo2{ Name="DebugLZQ",Age=26,TelTable=new List<string>(){"8888888","138******"}},
- new GustInfo2{ Name="博客园",Age=6,TelTable =new List<string>(){"666666","138******"}},
- new GustInfo2{ Name="M&MSoft",Age=9,TelTable=new List<string>(){"55555","138******"}}
- };
- //gust、tel都是查询变量,作用域为当前查询语句!!!
- var query2 = from gust in gList2
- from tel in gust.TelTable
- where tel.IndexOf("5555") > -1
- select gust;
- foreach (var g in query2)
- {
- Console.WriteLine("{0} 年龄{1}",g.Name,g.Age );
- foreach (var t in g.TelTable)
- {
- Console.WriteLine("电话:{0}",t);
- }
- }
- Console.ReadKey(false);
- //4多个from子句
- var query3 = from GustInfo gust in gList
- where gust.Age > 6
- from GustInfo2 gust2 in gList2
- where gust2.Age> 9
- select new { gust, gust2 };//查询结果定制
- foreach (var g in query3)
- {
- Console.WriteLine("{0} {1}", g.gust.Name, g.gust2.Name);
- }
- Console.ReadKey(false);
- }
- }
- }

程序的运行结果如下:
程序中列举了from子句的用法示例,注意复合from子句和多个from子句的书写,同时需要理解范围变量和数据源变量这两个概念。
2.where子句
where子句,它是LINQ表达式的元素筛选机制,除了开始和结束的位置,它几乎可以出现在LINQ表达式的任意位置上。
在一个LINQ表达式中,可以有where子句,也可以没有;可以有一个,也可以有多个;多个where子句之间的逻辑关系相当于逻辑“与”,每个 where子句可以包含1个或多个bool逻辑表达式,这些条件成为谓词,谓词逻辑之间用的是“&&”“||”等而不是SQL中的and 、or。

- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace LINQ_WHERE
- {
- /// <summary>
- /// LINQ where子句
- /// </summary>
- class Program
- {
- static void Main(string[] args)
- {
- //1常见的where语句
- List<GustInfo> gList = new List<GustInfo>()
- {
- new GustInfo(){ Name="DebugLZQ", Age=26,Tel="88888888"},
- new GustInfo(){ Name="cnblogs",Age=6,Tel="666666"},
- new GustInfo(){ Name="M&MSoft",Age=9,Tel="55555"}
- };
- var query = from gust in gList
- where (gust.Name.Length > 7 || gust.Name.Substring(0, 1) == "M") && gust.Age > 9
- select new { gust.Name, gust.Age };
- foreach (var g in query)
- {
- Console.WriteLine("{0},{1}", g.Name, g.Age);
- }
- Console.ReadKey(false);
- //2.在where子句中使用自定义函数
- var query2 = from GustInfo gust in gList
- where gust.Name.Length > 5
- && Check(gust.Name)
- select gust;
- foreach (var g in query2)
- {
- Console.WriteLine("{0},{1},{2}", g.Name, g.Age, g.Tel);
- }
- Console.ReadKey(false);
- //3.动态谓词的筛选
- //定义动态谓词数组,在实际开发中可以动态获得
- string[] names = { "SB","XXX","***","@@@","一些敏感词"};
- var query3 = from GustInfo guest in gList
- where !names.Contains(guest.Name)
- select guest;
- foreach (var q in query3)
- {
- Console.WriteLine("{0} 年龄:{1},电话:{2}",q.Name,q.Age,q.Tel );
- }
- Console.ReadKey(false);
- }
- //自定义函数
- static bool Check(string name)
- {
- if (name.Substring(0, 1) == "N")
- return false;
- return true;
- }
- }
- }

需要注意一些常用的where子句的写法。程序的运行结果如下:
3.Select子句
在select子句上可以非常灵活的处理查询到的元素,然后再把结果返回。

- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace LINQ_select
- {
- /// <summary>
- /// LINQ select
- /// 在select子句上,可以非常灵活的处理查询到的元素,然后再把结果返回
- /// </summary>
- class MyGustInfo
- {
- public string Name { get; set; }
- public int Age { get; set; }
- }
- class Program
- {
- static void Main(string[] args)
- {
- List<GustInfo> gList = new List<GustInfo>()
- {
- new GustInfo(){ Name="DebugLZQ", Age=25, Tel="88888888"},
- new GustInfo(){ Name="cnblogs", Age=6, Tel="666666"},
- new GustInfo(){ Name="M&M", Age=9, Tel="55555"}
- };
- var query = from gust in gList
- where gust.Age >= 9 && gust.Age <= 30
- select gust.Name.Replace("&", "mm");//select子句灵活应用
- var query2 = from gust in gList
- where gust.Age >= 9 && gust.Age <= 30
- select MyProc(gust.Name);
- var query3 = from gust in gList
- where gust.Age >= 9 && gust.Age <= 30
- select new { gust.Name,gust.Age};
- var query4 = from gust in gList
- where gust.Age >= 9 && gust.Age <= 30
- select new MyGustInfo { Name=gust.Name+"My", Age=gust.Age+1};//对查询结果进行投影
- foreach (var v in query)
- {
- Console.WriteLine(v);
- }
- foreach (var v in query2)
- {
- Console.WriteLine(v);
- }
- foreach (var v in query3)
- {
- Console.WriteLine(v.Name+v.Age );
- }
- foreach (var v in query4)
- {
- Console.WriteLine(v.Name+v.Age );
- }
- Console.ReadKey(false);
- }
- static string MyProc(string s)
- {
- return s + "Better";
- }
- }
- }

程序的运行结果如下:
4.group子句
根据语法的规定,LINQ表达式必须以from子句开头,以select或group子句结束,所以除了使用select来返回结果外,也可以使用group子句来返回元素分组后的结果。
group子句返回的是一个基于IGrouping<TKey,TElement>泛型接口的对象序列。
语法和SQL的group有点区别,不注意的话可能会写错。

- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace LINQ_group
- {
- /// <summary>
- /// LINQ group子句
- /// </summary>
- class Program
- {
- static void Main(string[] args)
- {
- List<GustInfo> gList = new List<GustInfo>()
- {
- new GustInfo(){ Name="DebugLZQ",Age=26,Tel="187********"},
- new GustInfo(){ Name="Sarah",Age=25,Tel="159********"},
- new GustInfo(){ Name="Jerry",Age=35,Tel="135********"},
- new GustInfo(){ Name="M&M",Age=16,Tel="136********"},
- new GustInfo(){ Name="DebugMan",Age=26,Tel="136********"},
- new GustInfo(){ Name="Jerry&Tom",Age=19,Tel="136********"},
- };
- var query = from guest in gList
- group guest by guest.Name.Substring(0, 1);//分组键key是string类型
- //遍历键值和键值所属元素
- foreach (IGrouping<string, GustInfo> guestGroup in query)
- {
- Console.WriteLine("分组键:{0}",guestGroup.Key );
- foreach (var g in guestGroup)
- {
- Console.WriteLine("{0} 年龄:{1} 电话:{2}",g.Name,g.Age,g.Tel );
- }
- }
- Console.ReadKey(false);
- Console.WriteLine("-----------------------------------");
- var query2 = from guest in gList
- group guest by guest.Age > 20;//分组键key是bool类型表达式的结果
- foreach (IGrouping<bool, GustInfo> guestGroup in query2)
- {
- Console.WriteLine("年龄是否大于20 分组键:{0}", guestGroup.Key);
- foreach (var g in guestGroup)
- {
- Console.WriteLine("{0} 年龄:{1} 电话:{2}", g.Name, g.Age, g.Tel);
- }
- }
- Console.ReadKey(false);
- }
- }
- }

程序的运行结果如下:
5.into子句
into子句作为一个临时标识符,用于group、select、join子句中充当其结果的引用。

- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace LINQ_into
- {
- /// <summary>
- /// LINQ group
- /// </summary>
- class Program
- {
- static void Main(string[] args)
- {
- List<GustInfo> gList = new List<GustInfo>()
- {
- new GustInfo(){ Name="DebugLZQ",Age=26,Tel="187********"},
- new GustInfo(){ Name="Sarah",Age=25,Tel="159********"},
- new GustInfo(){ Name="Jerry",Age=35,Tel="135********"},
- new GustInfo(){ Name="M&M",Age=16,Tel="136********"},
- new GustInfo(){ Name="DebugMan",Age=26,Tel="136********"},
- new GustInfo(){ Name="Jerry&Tom",Age=19,Tel="136********"},
- };
- //1.into用于group子句
- var query = from guest in gList
- group guest by guest.Name.Substring(0, 1) into grguest
- orderby grguest.Key descending
- select grguest;
- var query2 = from guest in gList
- group guest by guest.Name.Substring(0, 1) into grguest
- orderby grguest.Key ascending
- select grguest;
- //2.select 子句中的into子句
- var query3 = from guest in gList
- select new { NewName = guest.Name, NewAge = guest.Age } into newguest
- orderby newguest.NewAge
- select newguest;
- foreach (var guestGroup in query)
- {
- Console.WriteLine("分组键:{0}",guestGroup.Key );
- foreach (var g in guestGroup)
- {
- Console.WriteLine("{0} 电话:{1}",g.Name,g.Tel );
- }
- }
- Console.ReadKey(false);
- foreach (var newg in query3)
- {
- Console.WriteLine("{0} 年龄:{1}",newg.NewName,newg.NewAge );
- }
- Console.ReadKey(false);
- }
- }
- }

程序运行结果如下:
6.orderby子句、thenby子句
LINQ可以按照元素的一个或多个属性对元素进行排序。

- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace LINQ_orderby
- {
- class Program
- {
- /// <summary>
- /// LINQ orderby (ascending descending)
- /// </summary>
- /// <param name="args"></param>
- static void Main(string[] args)
- {
- List<GustInfo> gList = new List<GustInfo>()
- {
- new GustInfo(){ Name="DebugLZQ",Age=26,Tel="187********"},
- new GustInfo(){ Name="Sarah",Age=25,Tel="159********"},
- new GustInfo(){ Name="Jerry",Age=35,Tel="135********"},
- new GustInfo(){ Name="M&M",Age=16,Tel="136********"},
- new GustInfo(){ Name="DebugMan",Age=26,Tel="136********"},
- new GustInfo(){ Name="Jerry&Tom",Age=19,Tel="136********"},
- };
- //按照年龄排序
- var query = from guest in gList
- orderby guest.Age
- select guest;
- var query1 = from guest in gList
- orderby guest.Age ascending
- select guest;
- var query2 = from guest in gList
- orderby guest.Age descending
- select guest;
- //按照年龄进行排序,按照名字字数进行次要排序
- var query3 = from guest in gList
- orderby guest.Age, guest.Name.Length
- select guest;
- var query4 = from guest in gList
- orderby guest.Age descending , guest.Name.Length ascending
- select guest;
- var query5 = from guest in gList
- orderby guest.Age, guest.Name.Length,guest.Tel
- select guest;
- foreach (var guest in query2)
- {
- Console.WriteLine("{0} 年龄:{1} 电话:{2}",guest.Name,guest.Age,guest.Tel );
- }
- Console.ReadKey(false);
- foreach (var guest in query4)
- {
- Console.WriteLine("{0} 年龄:{1} 电话:{2}", guest.Name, guest.Age, guest.Tel);
- }
- Console.ReadKey(false);
- }
- }
- }

程序运行结果如下:
7.let子句
let子句用于在LINQ表达式中存储子表达式的计算结果。

- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace LINQ_let
- {
- /// <summary>
- /// LINQ let用来存子储表达式的计算结果
- /// </summary>
- class Program
- {
- static void Main(string[] args)
- {
- List<GustInfo> gList = new List<GustInfo>()
- {
- new GustInfo(){ Name="DebugLZQ",Age=26,Tel="187********"},
- new GustInfo(){ Name="Sarah",Age=25,Tel="159********"},
- new GustInfo(){ Name="Jerry",Age=35,Tel="135********"},
- new GustInfo(){ Name="M&M",Age=16,Tel="136********"},
- new GustInfo(){ Name="DebugMan",Age=26,Tel="136********"},
- new GustInfo(){ Name="Jerry&Tom",Age=19,Tel="136********"},
- };
- //使用let子句创建范围变量g,并通过g构建查询表达式
- var query = from guest in gList
- let g = guest.Name.Substring(0, 1)
- where g == "D" || g == "J"
- select guest;
- //也可以不使用let,上面的语句等效于下
- var query2 = from guest in gList
- where guest.Name.Substring(0, 1) == "D" || guest.Name.Substring(0, 1) == "J"
- select guest;
- foreach (var g in query)
- {
- Console.WriteLine("{0} 年龄:{1} 电话:{2}",g.Name,g.Age,g.Tel );
- }
- Console.ReadKey(false);
- Console.WriteLine("不使用let,等效的语句结果");
- foreach (var g in query2)
- {
- Console.WriteLine("{0} 年龄:{1} 电话:{2}", g.Name, g.Age, g.Tel);
- }
- Console.ReadKey(false);
- }
- }
- }

程序的运行结果如下:
8.join子句
如果一个数据源中元素的某个属性可以跟另外一个数据源的中元素的某个属性进行相等比较,那么这两个数据源可以用join子句进行关联。
join子句使用equals关键字进行相等比较,而不是常用的双等号。

- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace LINQ_join
- {
- class Program
- {
- static void Main(string[] args)
- {
- //定义两个数据源
- List<GustInfo> gList = new List<GustInfo>()
- {
- new GustInfo(){ Name="DebugLZQ",Age=26,Tel="187********"},
- new GustInfo(){ Name="Sarah",Age=25,Tel="159********"},
- new GustInfo(){ Name="Jerry",Age=35,Tel="135********"},
- new GustInfo(){ Name="M&M",Age=16,Tel="136********"},
- new GustInfo(){ Name="DebugMan",Age=26,Tel="136********"},
- new GustInfo(){ Name="Jerry&Tom",Age=19,Tel="136********"},
- };
- List<GuestTitle> titleList = new List<GuestTitle>()
- {
- new GuestTitle(){Name="DebugLZQ",Title="Soft Engineer"},
- new GuestTitle(){Name="DebugLZQ",Title="Team Leader"},
- new GuestTitle(){Name="Sarah",Title="Test Engineer"},
- new GuestTitle(){Name="Jerry",Title="Head Master"}
- };
- //1.根据姓名进行内连接
- var query = from guest in gList
- join title in titleList on guest.Name equals title.Name
- select new { Name=guest.Name ,Title=title.Title,Age=guest.Age };
- foreach (var g in query)
- {
- Console.WriteLine("{0} {1} 年龄:{2}",g.Name,g.Title ,g.Age );
- }
- Console.ReadKey(false);
- //前面的多个from实现相同的作用:与内连接区别在于:这个中间的操作是叉乘获得笛卡尔积
- var query2=from guest in gList
- from title in titleList
- where guest.Name==title.Name
- select new { Name = guest.Name, Title = title.Title, Age = guest.Age };
- foreach (var g in query2)
- {
- Console.WriteLine("{0} {1} 年龄:{2}", g.Name, g.Title, g.Age);
- }
- Console.ReadKey(false);
- //2.根据姓名进行分组连接
- //根据名字分组后,得到每个名字下的全部名称
- var query3 = from guest in gList
- join title in titleList on guest.Name equals title.Name into tgroup
- select new { Name=guest.Name,Titles=tgroup };
- foreach (var g in query3)
- {
- Console.WriteLine(g.Name);
- foreach (var g2 in g.Titles)
- {
- Console.WriteLine(" {0}",g2.Title );
- }
- }
- Console.ReadKey(false);
- //3.根据姓名进行左外连接
- //无职务的输出为空缺
- var query4 = from guest in gList
- join title in titleList on guest.Name equals title.Name into tgroup
- from subtitle in tgroup.DefaultIfEmpty()
- select new { Name=guest.Name,Title=subtitle==null?"空缺":subtitle.Title };
- foreach (var g in query4)
- {
- Console.WriteLine("{0} {1} ",g.Name ,g.Title );
- }
- Console.ReadKey(false);
- }
- }
- }

程序结果如下:
以上就是LINQ的基本子句的常用用法,文字不是很多,因为代码中都有详细的注释说明。其他的一些查询运算符,将在后面几篇博文中陆续总结~~
LINQ的基本语法包含如下的8个上下文关键字,这些关键字和具体的说明如下的更多相关文章
- Linq to SQL 语法查询(链接查询,子查询 & in操作 & join,分组统计等)
Linq to SQL 语法查询(链接查询,子查询 & in操作 & join,分组统计等) 子查询 描述:查询订单数超过5的顾客信息 查询句法: var 子查询 = from c i ...
- FreeSql (二十四)Linq To Sql 语法使用介绍
原本不支持 IQueryable 主要出于使用习惯的考虑,如果继承 IQueryable,编写代码的智能总会提示出现一堆你不想使用的方法(对不起,我有强迫症),IQueryable 自身提供了一堆没法 ...
- Linq中常用语法
using System;using System.Collections.Generic;using System.ComponentModel.Design;using System.Linq;u ...
- C#程序集系列04,在程序集包含多个module的场景下理解关键字internal
本篇在一个程序集包含多个module的场景下体验internal的含义. →查看F盘as文件夹下的文件→删除MainClass.exe→把MyFirstModule和MySecondModule组装到 ...
- [转]LINQ To SQL 语法及实例大全
转载自:http://blog.csdn.net/pan_junbiao/article/details/7015633 LINQ to SQL语句(1)之Where Where操作 适用场景:实现过 ...
- LINQ To SQL 语法及实例大全
http://blog.csdn.net/pan_junbiao/article/details/7015633 http://blog.csdn.net/pan_junbiao/article/de ...
- Linq to sql语法
LINQ to SQL语句(1)之Where Where操作 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子 ...
- Linq to Sql语法及实例大全
LINQ to SQL语句(1)之Where Where操作 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的 ,而判断条件就是它后面所接的 ...
- 【转】 LINQ To SQL 语法及实例大全
LINQ to SQL语句(1)之Where Where操作 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子 ...
随机推荐
- 紫书 例题 11-14 UVa 1279 (动点最小生成树)(详细解释)
这道题写了好久-- 在三维空间里面有动的点, 然后求有几次最小生成树. 其实很容易发现, 在最小生成树切换的时候,在这个时候一定有两条边相等, 而且等一下更大的那条边在最小生成树中,等一下更小的边不在 ...
- WPF 一个空的 WPF 程序有多少个窗口
原文:WPF 一个空的 WPF 程序有多少个窗口 好多小伙伴说 WPF 的程序有五个窗口,但是我尝试使用了 EnumThreadWindows 去获取的时候居然拿到了 10 多个窗口 在 WPF 内部 ...
- hdu_1166,线段树单点更新
在刷线段树,参考自http://www.notonlysuccess.com/index.php/segment-tree-complete/ #include<iostream> #in ...
- matplotlib 可视化 —— 定制 matplotlib
1. matplotlibrc 文件 matplotlib使用matplotlibrc [matplotlib resource configurations] 配置文件来自定义各种属性,我们称之为 ...
- Git-如何将已存在的项目提交到git
1.首先在码云或者github上创建一个不带README.md的项目,然后复制远程库的地址(下面以码云为例): 2.进入本地已存在的项目目录:house touch README.md //新建说明 ...
- django 笔记6 Ajax
感谢alex~ .Django请求生命周期 输入url 进入 urls(路由系统) 指向 views(视图函数)->(获取模板) 里面的函数 再由函数返回字符串给用户 .路由系统 /index/ ...
- UVa 1599 Ideal Path【BFS】
题意:给出n个点,m条边,每条边上涂有一个颜色,求从节点1到节点n的最短路径,如果最短路径有多条,要求经过的边上的颜色的字典序最小 紫书的思路:第一次从终点bfs,求出各个节点到终点的最短距离, 第二 ...
- 51Nod 不重叠的线段(贪心)
X轴上有N条线段,每条线段有1个起点S和终点E.最多能够选出多少条互不重叠的线段.(注:起点或终点重叠,不算重叠). 例如:[1 5][2 3][3 6],可以选[2 3][3 6],这2条线段互不重 ...
- 解决高版本vm打开虚拟机报错
问题: 打开虚拟机的文件目录,找到.vmx 文件 用记事本打开重命名后的“.vmx.txt”文件 找到行:policy.vm.mvmtid = "52 10 08 ed ff 34 ed d ...
- 仿函数(functor)
仿函数(functor),就是使一个类的使用看上去像一个函数.其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了. In computer programmin ...