出于工作需要,准备把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个上下文关键字,这些关键字和具体的说明如下的更多相关文章

  1. Linq to SQL 语法查询(链接查询,子查询 & in操作 & join,分组统计等)

    Linq to SQL 语法查询(链接查询,子查询 & in操作 & join,分组统计等) 子查询 描述:查询订单数超过5的顾客信息 查询句法: var 子查询 = from c i ...

  2. FreeSql (二十四)Linq To Sql 语法使用介绍

    原本不支持 IQueryable 主要出于使用习惯的考虑,如果继承 IQueryable,编写代码的智能总会提示出现一堆你不想使用的方法(对不起,我有强迫症),IQueryable 自身提供了一堆没法 ...

  3. Linq中常用语法

    using System;using System.Collections.Generic;using System.ComponentModel.Design;using System.Linq;u ...

  4. C#程序集系列04,在程序集包含多个module的场景下理解关键字internal

    本篇在一个程序集包含多个module的场景下体验internal的含义. →查看F盘as文件夹下的文件→删除MainClass.exe→把MyFirstModule和MySecondModule组装到 ...

  5. [转]LINQ To SQL 语法及实例大全

    转载自:http://blog.csdn.net/pan_junbiao/article/details/7015633 LINQ to SQL语句(1)之Where Where操作 适用场景:实现过 ...

  6. LINQ To SQL 语法及实例大全

    http://blog.csdn.net/pan_junbiao/article/details/7015633 http://blog.csdn.net/pan_junbiao/article/de ...

  7. Linq to sql语法

    LINQ to SQL语句(1)之Where Where操作 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子 ...

  8. Linq to Sql语法及实例大全

    LINQ to SQL语句(1)之Where Where操作 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的 ,而判断条件就是它后面所接的 ...

  9. 【转】 LINQ To SQL 语法及实例大全

    LINQ to SQL语句(1)之Where Where操作 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子 ...

随机推荐

  1. BZOJ 4236~4247 题解

    BZOJ 4236 JOIOJI f[i][0..2]表示前i个字符中′J′/′O′/′I′的个数 将二元组<f[i][0]−f[i][1],f[i][1]−f[i][2]>扔进map,记 ...

  2. UVA 11825 - Hackers&#39; Crackdown 状态压缩 dp 枚举子集

    UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集 ACM 题目地址:option=com_onlinejudge&Itemid=8&page=sh ...

  3. DM8168 屏蔽 PCIe

    DM8168新板在没有做PCI接口的情况下,能够把PCI模块凝视,直接尝试: make CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm menuconfi ...

  4. jsp中对话框的实现

    <Input type=submit name="g" style="font-size:20px" value="提交" oncli ...

  5. android删除表和清空表

    删除某一表: //删除某一个表 public void dropTable(SQLiteDatabase db){ db.execSQL("drop from tab_name") ...

  6. poj--2385--Apple Catching(状态dp)

    Apple Catching Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submi ...

  7. Anaconda升级

    Anaconda是可以进行升级的, 这样就省的重装一遍python全家桶了, 比如:   conda update conda conda install anaconda=2018.12   就可以 ...

  8. 网络通信-ping命令

  9. 【DNN】 制作一个扩展程序

    Select Extension Type Authentication system 认证系统 Container 容器. Core Language Pack 核心语言包 Dashboard Co ...

  10. Internet Explorer Developer Channel 自动化测试 IE 浏览器

    IE 原生 Web Driver 调用,通过简单配置,即可自动化测试 IE 浏览器(目前仅限 Internet Explorer Developer Channel 版本).做一些自动化的操作,都是很 ...