LINQ语法详解

我会通过一些列的实例向大家讲解LINQ的语法。

先创建一个Person类,作为数据实体

    public class Person
    {
        public string Name
        {
            get;
            set;
        }
        public string Sex
        {
            get;
            set;
        }
        public int Age
        {
            get;
            set;
        }
    }
 List<Person> list = new List<Person>()
 {
    new Person(){ Name="Olive",Sex="女",Age=22},
    new Person(){ Name="Moyao",Sex="男",Age=23},
    new Person(){ Name="Momo",Sex="女",Age=22},
    new Person(){ Name="Only",Sex="女",Age=20},
    new Person(){ Name="Love",Sex="女",Age=21},
    new Person(){ Name="For",Sex="女",Age=22},
    new Person(){ Name="Remote",Sex="男",Age=23},
    new Person(){ Name="Snow",Sex="女",Age=23}
 };
    //从list集合中选出性别为“女”的人
    var girls = from g in list
                where g.Sex == "女"
                select g;
    //从list集合中选出性别为“男”的人
    var boys = list.Where(p => p.Sex == "男");

    Console.WriteLine("girl" + System.Environment.NewLine);
    foreach (var g in girls)
    {
        Console.WriteLine("姓名:" + g.Name + "--性别:" + g.Sex + "--年龄:" + g.Age);
        Console.WriteLine(System.Environment.NewLine);

    }

    context.Response.Write("boy" + System.Environment.NewLine);
    foreach (var b in boys)
    {
        Console.WriteLine("姓名:" + b.Name + "--性别:" + b.Sex + "--年龄:" + b.Age);
        Console.WriteLine(System.Environment.NewLine);
    }

输出结果如下:

细心的朋友们可能会发现从list集合中获取信息的方式不一样,在获取性别为“女”的集合中采用的是from g in list where g.Sex== "女" select g;

而在获取性别为“男”的集合中采用的为list.Where(p => p.Sex == "男");

或许会有人问,这两种查询方式有什么区别呢?上面的第一种方法叫查询语法(query syntax),看上去和SQL的语句很相似。查询语法使用查询表达式书写。第二种方法叫方法语法(method syntax)是命令形式,它使用的是标准的方法调用,方法是一组叫做标准查询运算符的方法。虽然形式上这两种查询方法不同,事实上这两种方法存在着紧密的联系,在CLR内只识别查询方法,因此在每次查询的时候编译器在编译时会将查询语句翻译为查询方法,当然大部分的查询方法也都有对应的查询语句形式,例如:where对应Where(),select对应Select(),orderby对应orderby(),group对应group(),join对应Join(),distinct对应Distinct(),union对应Union(),Intersect对应Intersect(),except对应Except(),等等。

我们看SQL查询形式:select查询内容 from数据源 where查询条件,也就是分为数据源、查询条件、查询内容这三部分,在LINQ查询里也是分这三部分,从上面的例子中我们可以知道它的查询方式是这样的from a(查询内容) in数据源 where查询条件 select a(查询内容)

下边就从最基本的介绍开始。

1、from

在SQL里边from后跟的是数据源,当然在LINQ里from子句指定的也是要作为数据源使用的数据集合,但是它引入了迭代变量,迭代变量有序表示数据源的每一个元素,最后查询返回的是一个迭代变变量的集合。

2、Where/where()

在SQL里where后跟的是查询条件,在LINQ里也是一样的。

请看示例:

//查询年龄大于21且性别为女的人员的个人信息
var girls1 = from g in list
where g.Age > 21 && g.Sex == "女"
select g;

//使用查询方法查询
var girls1 = list.Where(g => g.Age > 21 && g.Sex == "女");
Console.WriteLine("年龄大于21且性别为女的个人信息:");

foreach (var g in girls1)
{
  Console.WriteLine("姓名:" + g.Name + "--性别:" + g.Sex + "--年龄:" + g.Age);
}

实验结果:

从实验结果中我们可以看到,在查询语句中where后边也可以跟一个或多个查询条件,去筛选数据,以得到想要的结果,或许还有人对使用查询方法有点疑问,查询方法where()里边的参数到底是什么呢?这里就用到了上一节我们讲的Lambda表达式。

请看Where()的原型:

where()语法是:

public static IEnumerable<TSource> where<TSource>(
this IEnumerable<TSource> source,
Func<TSource,bool> predicate)

由上一节学的知识我们可以知道该方法是一个泛型的扩展方法,该方法只接受一个Func<TSource,bool>泛型委托参数,这里的predicate是一个判断条件。

我们上边用的list.Where(g=>g.Age>21 && g.Sex) 高亮部分就相当于一个委托参数,所以用where()查询方法才能查出符合条件的信息。至于上边提到的Selec()、Orderby()等查询方法语法原型都是泛型的扩展方法和where()差不多,后边就不再过多的介绍其方法原型了。

3、select/select()

select筛选出符合条件的数据

用查询语句查询var g1=from g in list where g.Name="Olive" select g1;

用查询方法查询姓名为Olive的人员信息:

var g1 = list.Select(p=>p).Where(p=>p.Name == "Olive");

结果如下:

4、排序:orderby/OrderBy()、thenBy()、ThenByDescending()

//用orderby进行排序(默认升序)
Var ps=from p in list select p orderby

//用OrderBy()进行排序(升序)
var g11 = list.OrderBy(p => p.Age);

结果如图:

//用orderby descending降序排列
var ps=from p in list select p orderby p.Age descending

//用OrderByDescending()降序排序
var g11 = list.OrderByDescending(p => p.Age);

结果如图:

用ThenBy()做二次排序,先按年龄的升序排序,如果年龄相等的就再按姓名升序排序

var g12 = list.OrderBy(p => p.Age).ThenBy(p => p.Name);

结果如图:

用ThenByDescending()做二次排序,先按年龄的升序排序,如果年龄相等的就再按姓名降序排序

var g12 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name);

结果如图:

5、group/GroupBy()

使用group子句可产生按照指定的键组织的组序列。

//用group子句进行分组
Var ps=from p in list group p.Sex into p select p;

//使用GroupBy()进行分组
var g11 = list.OrderByDescending(p => p.Age).GroupBy(p=>p.Sex);

结果如下:

6、Take、TakeWhile、Skip、SkipWhile

6.1、Take:用于从输入序列中返回指定数量的元素

//从满足条件的的序列中返回3条信息

var g12 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Take(3);

6.2、TakeWhile:只要满足一定条件的就会马上返回序列元素

var g12 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).TakeWhile(p=>p.Sex=="女");

结果如图:

6.3 、Skip:用于从输入序列中跳过指定个数的元素,返回由序列中剩余的元素所组成的新序列

//跳过4个指定元素,然后将剩余的元素组成新序列返回
var g12 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Skip(4);

6.4、SkipWhile:用于从输入序列中跳过满足一定条件指定数量的元素,返回由序列中剩余的元素所组成的新序列

//跳过姓名为“Olive”的信息,然后将剩余的的元素组成新的序列返回

var g12 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).SkipWhile(p=>p.Name=="Olive");

结果如下:

7、Count(),Max()/Min(),Average(),Sum()聚合方法

7.1、Count():统计序列中元素个数

示例:

var g121 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Count();
Console.WriteLine("总共有{0}条信息!"+g121);

结果:

7.2、Max()/Min()求最大/最小值

示例:

//求最大年龄:
var g121 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Max(p => p.Age);
Console.WriteLine("最大年龄为:"+g121);

结果:

示例:

//求最小年龄:
var g121 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Min(p => p.Age);
Console.WriteLine("最小年龄为:"+g121);

结果:

7.3、Average()求平均值

示例:

//求平均年龄:
var g121 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Average(p => p.Age);
Console.WriteLine("平均年龄为:"+g121);

结果:

7.4、Sum()累加求和

示例:

//累加年龄:
var g121 = list.OrderBy(p => p.Age).ThenByDescending(p => p.Name).Average(p => p.Age);
Console.WriteLine("累加年龄为:"+g121);

结果:

8、Join(),GroupJoin(),Union(),Intersect(),Except(),Contact(),Distinct操作符

8.1、Join()用于连接两个序列,和SQL里的Join语句连接多表一样,连接操作接受两个集合然后创建一个临时的对象集合,每个对象包含原始集合对象中的所有字段,使用连接来结合两个或更多个集合中的数据。

例如:

//这里使用上边新建的Person类,然后在新建一个Profession(职业)类
Public class Profession
{
    Public string Name{get;set:}
    Public string Zhiye{get;set;}
}

List<Person> list=new List<Person>()
{
    new Person(){ Name="Olive",Sex="女",Age=22},
    new Person(){ Name="Moyao",Sex="男",Age=23},
    new Person(){ Name="Momo",Sex="女",Age=22},
    new Person(){ Name="Only",Sex="女",Age=20},
    new Person(){ Name="Love",Sex="女",Age=21},
    new Person(){ Name="For",Sex="女",Age=22},
    new Person(){ Name="Remote",Sex="男",Age=23},
    new Person(){ Name="Snow",Sex="女",Age=23}
};

List<Profession> listprofession = new List<Profession>
{
    new Profession() { Name = "Olive", ZhiYe = "会计" },
    new Profession() { Name = "Remote", ZhiYe = "IT Coder" },
    new Profession() { Name = "BLove", ZhiYe = "学生" },
    new Profession(){ Name="AFor",ZhiYe="作家"}
};

//使用Join查询语句查询,从Person序列和Profession序列里查询出姓名相同的信息,组合成一个新的序列,并显示姓名和职业
var showzhiye = from p in list
join pf in listprofession on p.Name equals pf.Name
select new
{
    Name = p.Name,
    ZhiYe = pf.ZhiYe
};

foreach (var p in showzhiye)
{
    Console.WriteLine("姓名:" + p.Name + "职业:" + p.ZhiYe);
}

//使用Json()方法查询:
var showzhiye = list.Join(listprofession, p => p.Name, pf => pf.Name, (p, pf) => new
{
    Name = p.Name,
    ZhiYe = pf.ZhiYe
});  

两种方法查询的结果一样如下:

8.2、GroupJoin():将基于键相等对两个序列的元素进行关联并对结果进行分组。使用默认的相等比较器对键进行比较。

var showzhiye = list.GroupJoin(listprofession, p => p.Name, pf => pf.Name, (p, pf) => new{ Name = p.Name, ZhiYe = pf.Max(pf1=>pf1.Name)});

var showzhiye = listprofession.GroupJoin(list, pf => pf.Name, p => p.Name, (pf, p) => new
{
    Name = pf.Name,
    ZhiYe =pf.ZhiYe,
    Count=p.Count()
});

结果:

8.3、Union():用于将两个输入序列中的元素合并成一个新的序列,且新序列中自动去除重复的序列

示例:

List<Person> list1 = new List<Person>()
{
    new Person(){ Name="Olive",Sex="女",Age=18},
    new Person(){ Name="Moyao",Sex="男",Age=19},
    new Person(){ Name="Momo",Sex="女",Age=20},
    new Person(){ Name="Olive116",Sex="女",Age=18},
    new Person(){ Name="Moyao116",Sex="男",Age=19},
    new Person(){ Name="Momo116",Sex="女",Age=20},
};

var uniontest = list.Union(list1);//将list1和上边所示的list合并,自动去除重复列

foreach (var p in uniontest)
{
    Console.WriteLine("姓名:" + p.Name + "年龄:"+p.Age +"性别:"+p.Sex );
}

结果:

8.4、Intersect():求两个序列的交集,将两个序列中相同的元素挑选出来组成一个新的序列

这里还是用8.3里的数据源list1、list

示例:

var intersectTest = list1.Intersect(list);
foreach (var p in intersectTest)
{
    Console.WriteLine("姓名:" + p.Name + "年龄:"+p.Age +"性别:"+p.Sex );

}

结果:

8.5、Except(),现有A、B两序列,返回仅在A序列中的元素所组成的序列,相当于求差集

var ExceptTest = list.Except(list1);

8.6、Contact():联接两个序列

示例:

var ExceptTest = list.Concat(list1);
foreach (var p in ExceptTest)
{
    Console.WriteLine("姓名:" + p.Name + "年龄:"+p.Age +"性别:"+p.Sex );
}

结果:

8.7、Distinct():检测每一个输入元素是否有相同的,如果有相同的元素则作为一个元素添加到结果序列中,相当于去除重复;

示例:list.Distinct();

本来想在这一节把所有的LINQ语法给全部讲完的,才发现这一节已经讲了很多了,这一节就讲到这里吧,给大家一个吸收消化的时间,在下一节里我会把剩下的LINQ语法给全部讲完。希望能给大家带来一些帮助。也请大家多多指教。

时间: 2024-08-07 07:05:29

LINQ语法详解的相关文章

C# LINQ语法详解

1.简单的linq语法 //1 var ss = from r in db.Am_recProScheme select r; //2 var ss1 = db.Am_recProScheme; //3 string sssql = "select * from Am_recProScheme"; 2.带where的查询 //1 var ss = from r in db.Am_recProScheme where r.rpId > 10 select r; //2 var ss

Linq之旅:Linq入门详解(Linq to Objects)

示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集成查询).通过LINQ,我们可以使用相同API操作不同的数据源.接下来就让我们看看LINQ是什么以及如何使用? 再此之前,需要先了解的相关技术 1. 隐式类型.匿名类型.对象初始化器 1) 隐式类型,使用var关键字创建,C#编译器会根据用于初始化局部变量的初始值推断出变量的数据类型.(不过我个人认

Java8初体验(二)Stream语法详解

原文链接:http://ifeve.com/stream/ 1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elements supporting sequential and parallel aggregate operations. 我们来解读一下上面的那句话: Stream是元素的集合,这点让Stream看起来用些类似Iterator: 可以支持顺序和并行的对原Stream进行汇聚的操作: 大家可以把Stream当成一个高级版本的

Hadoop Hive sql语法详解

Hive 是基于Hadoop 构建的一套数据仓库分析系统,它提供了丰富的SQL查询方式来分析存储在Hadoop 分布式文件系统中的数据,可以将结构化的数据文件映射为一张数据库表,并提供完整的SQL查询功能,可以将SQL语句转换为MapReduce任务进行运行,通过自己的SQL 去查询分析需要的内容,这套SQL 简称Hive SQL,使不熟悉mapreduce 的用户很方便的利用SQL 语言查询,汇总,分析数据.而mapreduce开发人员可以把己写的mapper 和reducer 作为插件来支持

[持续交付实践] pipeline:pipeline 使用之语法详解

一.引言 jenkins pipeline语法的发展如此之快用日新月异来形容也不为过,而目前国内对jenkins pipeline关注的人还非常少,相关的文章更是稀少,唯一看到w3c有篇相关的估计是直接翻译软件翻的,读下来惨不忍睹.没办法,语法详解这章我干脆把jenkins官网上的语法说明全部翻译了一遍,并更新了陈旧的内容(可怜了我大学四级的英语水平~),英语好的朋友也可以直接到官网阅读. 二.语法简介 Pipeline最基本的部分是"step".基本上,step告诉Jenkins 要

less中的部分语法详解

less中的语法详解,主要是介绍一些平时常用的语法,如果有更多更实用的语法欢迎大家和我交流. 一.变量. 变量是识别符号是@,在less中以@开头的则是变量,关于变量名的命名方法,大家可以参考js中命名的规则,毕竟是做前端的,有着统一的习惯有助于我们统一风格.个人推荐变量名的命名规则使用驼峰命名法.第一个单词首写字母小写,从第二个开始,单词首写字母大写.如boxAaa,boxBbbb,boxContainer,……,当然也是可是使用香肠命名法用下划线“_”来命名.如,box_main,borde

JSP语法详解

转自:http://www.cnblogs.com/culffe/articles/1142388.htm ———————————————————————————————————— 1)HTML注释: <!-- 注释内容 [ <%= 表达式 %> ] --> 可以用注释内容,也可以用表达式. 2)隐藏注释: <%-- 注释内容 --%> 注释会被JSP编译时被忽略.编译器不会对<%-- --%>之间的语句编译,它不会显示在客户的浏览器和源代码中. 3)声明:

Velocity魔法堂系列二:VTL语法详解

一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力.而且Velocity被移植到不同的平台上,如.Net的NVelocity和js的Velocity.js,虽然各平台在使用和实现上略有差别,但大部分语法和引擎核心的实现是一致的,因此学习成本降低不少哦. 最好的学习资源——官网:http://velocity.apache.org/ 本系列打算采用如下结构对Velocity进行较为

Android.mk 文件语法详解

转:http://blog.sina.com.cn/s/blog_602f8770010148ce.html ===================================================================================== 0. Android.mk简介: Android.mk文件用来告知NDK Build 系统关于Source的信息. Android.mk将是GNU Makefile的一部分,且将被Build System解析一次或多次