APS.NET MVC + EF (01)---Linq和Lambda表达式

1.1 Linq介绍

LINQ全称 Language Integrated Query(语言集成查询)。为我们提供一种统一的方式来查询和操作各种数据。

  • LINQ to Object:是针对实现了IEnumerable<T>的对象的LINQ;
  • LINQ to SQL:是针对关系数据库的LINQ;
  • LINQ to XML:是针对XML文档的LINQ。

LINQ除了提供一个统一的API来操作各种数据,并且为我们提供了编译时类型检查和动态创建查询表达式的能力。

LINQ查询时有两种语法可供选择:查询表达式语法(Query Expression)和方法语法(Fluent Syntax)。这两种方法是互补的。

1.1.1 查询表达式语法

基本语法:

from 变量 in 数据源对象

[where 条件]

[group 变量 by 表达式 into 临时标识符]

[orderby 表达式]

select 选择列

示例1:

static void Main(string[] args)

{

int[] nums = { 10, 15, 20, 25, 30 };

// 从数组中查询所有偶数

var result = from n in nums

where n % 2 == 0

select n;

// 输出查询结果

foreach(int num in result)

{

Console.WriteLine(num);

}

}

说明:

1、查询表达式语法与SQL(结构查询语言)语法相同。

2、查询语法必须以from子句开头,可以以Select或GroupBy子句结束 。

3、使用各种其他操作,如过滤,连接,分组,排序运算符以构造所需的结果。

4、隐式类型变量 - var可以用于保存LINQ查询的结果。

1.1.2 方法语法

方法语法(也称为流利语法)主要利用System.Linq.Enumerable类中定义的扩展方法和Lambda表达式方式进行查询。

例如示例1中的查询可以由以下方式代替,运行结果一致。

var result = nums.Where(n => n % 2 == 0);

关于Lambda表达式的语法,我们在后面的内容中进行详细讲解。

1.1.3 查询表达式语法VS方法语法

查询表达式语法与方法语法存在着紧密的关系

1、CLR本身并不理解查询表达式语法,它只理解方法语法。

2、编译器负责在编译时将查询表达式语法翻译为方法语法。

3、大部分方法语法都有对应的查询表达式语法形式:如Select()对应select、OrderBy()对应orderby

4、部分查询方法目前在C#中还没有对应的查询语句:如Count()和Max()

1.2 Linq之查询语法

1.2.1 排序

用where子句找到感兴趣的数据后,Linq还可以方便的对得到的数据执行进一步处理,例如,给结果重新排序。下面的示例将以字母顺序给上一个查询的结果排序

示例2

static void Main(string[] args)

{

string[] names = { "alonso", "zheng", "smith", "jones", "smythe", "small", "Ruiz", "Hsieh", "Jorgenson", "Ilyich", "singh" };

var result = from n in names where n.StartsWith("s") orderby n select n;

Console.WriteLine("以s开头的名字为:");

foreach (var item in result)

{

Console.WriteLine(item);

}

}

示例说明:

  • 这个程序与示例1几乎相同,只是在查询子句中增加了一行代码:

orderby n

即实现了对结果的排序功能。与where子句一样,orderby子句是可选的。

  • Orderby子句默认为升序,但可以添加descending关键字,指定降序排列。如:

orderby n descending;

  • 可以按照任意表达式进行排序,而无需重新编写查询。例如,要按照姓名中的最后一个字母顺序排序,只需添加如下子句:

orderby n.Substring(n.Length-1);

1.2.2 合计运算符

运算符

说明

Count()

结果的个数

Min()

结果中的最小值

Max()

结果中的最大值

Average()

数字结果的平均值

Sum()

所有数字结果的和

示例3

class Program

{

static void Main(string[] args)

{

int[] numbers = CreateNumbers(12345);

var result = from n in numbers where n > 1000 select n;

Console.WriteLine("大于1000的个数为:" + result.Count());

Console.WriteLine("大于1000的最大数为:" + result.Max());

Console.WriteLine("大于1000的最小数为:" + result.Min());

Console.WriteLine("大于1000的平均数为:" + result.Average());

Console.WriteLine("大于1000的数的和为:" + result.Sum(n=>(long)n));

}

private static int[] CreateNumbers(int count)

{

Random rand = new Random(0);

int[] result = new int[count];

for (int i = 0; i < count; i++)

{

result[i] = rand.Next();

}

return result;

}

}

示例说明:

示例3中的Sum()方法传入了一个Lambda表达式n=>(long)n,以获得所有数字的和。这是Sum()方法的一个重载。由于和的结果太大,若个只是用Sum()会产生溢出。

1.2.3 查询复杂对象

示例4

// Student类

class Student

{

public int ID { get; set; }

public string Name { get; set; }

public string Sex { get; set; }

public int Age{ get; set; }

public int Class { get; set; }

public override string ToString()

{

return "ID:" + ID + "\tName:" + Name + "\tSex:" + Sex + "\tAge:" + Age + "\tClass:" + Class;

}

}

//main 方法

static void Main(string[] args)

{

List<Student> list = new List<Student>{

new Student{ID=1,Name="zhangsan",Sex="男", Age=18,Class=50},

new Student{ID=2,Name="lisi",Sex="男", Age=18,Class=50},

new Student{ID=3,Name="wuangwu",Sex="男", Age=20,Class=51},

new Student{ID=4,Name="zhaoliu",Sex="男", Age=20,Class=52},

new Student{ID=5,Name="zhouqi",Sex="女", Age=21,Class=52},

new Student{ID=6,Name="wangba",Sex="女", Age=20,Class=52}

};

var result = from stu in list where stu.Age == 18 select stu;

Console.WriteLine("年龄为18的学员为:");

foreach (var stu in result)

{

Console.WriteLine(stu);

}

}

1.2.4 投射:在查询中创建新对象

投射是在Linq查询中从其它数据类型中创建新数据类型的技术术语。Select关键字是投射运算符。

如Sql数据查询语言,select用来从数据表中选择适当的字段,在Linq中select与其类似。例如将示例4中的代码改为如下:

var result=from stu in list where stu.Age=18 select stu.Name;

甚至可以通过给select添加表达式,来转换查询中的数据。如:

select stu.Name.ToUpper();

但是与sql不同,Linq不允许在select子句中有多个字段,即select stu.Name,stu.Age这样的形式将产生一个错误。如果要实现上述情况,需要在select子句中创建一个新对象,来保存查询的结果,如示例5所示。

示例5

//修改示例4Main方法

var result = from stu in list where stu.Age == 18

select new (stu.Name,stu.Age);

Console.WriteLine("年龄为18的学员为:");

foreach (var stu in result)

{

Console.WriteLine(stu);

}

1.2.5 多级排序

处理了带多个属性的对象后,要考虑按多种方式进行排序的问题了,例如我们先按照班级排序,在按照年龄排序。代码如下:

var result=from stu in list orderby stu.Class,stu.Age select stu;

还可以给字段添加Descending关键字。如

orderby stu.Class,stu.Age.deseending;

1.2.6 分组查询

在Linq中还可以实现像Sql中的Group by语句一样的分组统计功能。

示例6

var result=from stu in list

group stu by stu.Class into student

select new {Class=student.Key,Count=student.Count()};

var orderresult=from student in result

orderby student.Count descending

select student;

在分组查询中的数据通过一个键(key)字段来分组,每个组中的所有程序都共享这个字段值,在此例中键字段是Class:

group stu by stu.Class

要计算每个组的数量,应该生成一个新的结果集student(可自定义):

group stu by stu.Class into student

1.2.7 Join查询

Join可以用一个查询搜索两个列表中相关的数据,用关键字段把结果连接起来。类似于SQL中join(内连接)操作。如:

var result = from stu in list join scr in Scores

on stu.ID equals scr.ID

select new { stu.ID, stu.Name, scr.score };

foreach (var ss in result)

{

Console.WriteLine(ss);

}

1.3 Linq之方法语法

1.3.1 Lambda表达式

Lambda表达式用来实现一个匿名方法,其语法为:

(参数列表)=> 语句或语句块

这是一个简单的Lambda表达式: (item)=>item<1000;

运算符 "=>"称为Lambda表达式。这个表达式定义了一个方法,其参数是item,如果item小于1000,该方法就返回ture,否则返回false。该方法是一个没有名称的匿名方法。

  1. 如果我们只有一个参数,我们也可以删除(),代码如下:

    item=>item<1000;

  2. 如果需要传递多个参数,那么必须将参数括在括号内

    (ints,item)=>ints.Contains(item);

  3. 在Lambda表达式中可以没有参数,如下所示:

    ( ) =>Console.WriteLine("这是一个不带参数的Lambda表达式");

  4. 如果正文表达式中有多条语句,那么必须用大括号将正文表达式括起来,如下所示:

    (ints, item) => {

    Console.WriteLine("这是包含多条语句的Lambda表达式");

    return ints.Contains(item);

    };

  5. Func委托

    当需要指定Lambda表达式返回结果的类型时,可以使用Func<T,TResult>委托。如下所示:

    Func<int[], bool> isContains= p=> p.Equals(10);

    int[] ints= { 5 ,2 ,0, 66, 32, 7};

    bool result=isContains(ints);

1.3.2 在Linq中使用Lambda表达式

回顾示例2中的代码:

var result = from n in names where n.StartsWith("s") select n;

我们可以用方法语法来实现:

var result = names.Where(n => n.StartsWith("s"));

我们发现,用法方法查询语法更加简洁。

  1. 过滤(筛选)

    上面代码中Where()方法用来筛选,返回符合条件的子集。

  2. 排序(OrderBy、OrderByDescending、ThenBy、ThenByDescending)

    对上面的查询结果排序可以使用如下语句。

    var result = names.OrderBy(n => n).Where(n => n.StartsWith("s"));

    或者

    var result = names.Where(n => n.StartsWith("s")).OrderBy(n=>n);

    方法调用的顺序不是固定的,只要Linq方法返回值为IEnumerable类型即可,可以按照容易理解的方式来使用。此规则适合于以后讲到的其他方法。

    OrderBy()方法需要传入一个Lambda表达式用来告诉它用于排序的方法是什么,我们传送了最简单的Lambda表达式n=>n,因为只需要按照元素本身排序。还可以向上一章所讲那样按照最后一个字母进行排序:n=>n.Substring(n.Length-1)

    为了给元素逆序排序,可以调用OrderByDescending()方法,使用方法和OrderBy()相同。

多级排序可以使用ThenBy()方法。例如:

var result=list.OrderBy(stu=>stu.Class)

.ThenBy(stu=>stu.Age)

.ThenBy(stu=>stu.Name)

.Select(stu=>new {stu.Name,stu.Age,stu.Class});

多字段列表可以用在查询语法的OrderBy子句中。但在方法语法中第一项排序字段必须使用OrderBy()方法,随后使用ThenBy()方法。

如果第一个字段是以降序排序,需要使用OrderByDescending()方法,其他字段降序排序需要使用ThenByDescending()方法。

  1. 投射(Select)

    Select()方法用于方法语法的投射。示例5的功能可以通过下面代码实现。

    var result=list.Where(stu=>stu.Age==18)

    .Select(stu=>new {stu.Name,stu.Age,stu.Class});

  2. Any 和 All

    我们常常需要一类查询,确定数据是否满足某个条件,或者确保所有的数据都满足某个条件。例如,需要确定某个产品是否没有货了(库存为0)。

    Linq提供了两个布尔方法:Any() 和 All(),它们可以快速确定对于数据而言,某个条件是true还是false。如下面示例所示:

bool anyStu = list.Any(stu => stu.Sex == "男");

if (anyStu)

{

Console.WriteLine("学员中有男同学");

}

else

{

Console.WriteLine("学员中没有男同学");

}

bool allStu = list.All(stu => stu.Sex == "男");

if (allStu)

{

Console.WriteLine("学员中全部是男同学");

}

else

{

Console.WriteLine("学员中不全是男同学");

}

  1. Take 和 Skip

    Take()方法对应SQL语句中的Top运算符。与Take()方法相反的是Skip()方法,它可以跳过前n个结果,返回剩余的结果。例如:

var result = list.OrderBy(stu => stu.Age);

Console.WriteLine("年龄最小的两名学员是:");

foreach (var stu in result.Take(2))

{

Console.WriteLine(stu);

}

Console.WriteLine("其他学员依次为:");

foreach (var stu in result.Skip(2))

{

Console.WriteLine(stu);

}

  1. First 和 FirstOrDefault

    First()方法用来查找集合中第一个匹配的元素,如果没有找到匹配的结果则会引发一个异常。可以使用FirstOrDefault()方法避免异常的发生,若没有找到则返回有一个空。

    示例代码:

Console.WriteLine("姓名为lisi的同学信息:");

Console.WriteLine(list.First(stu => stu.Name == "lisi"));

Console.WriteLine("姓名为hanjiu的同学信息:");

Console.WriteLine(list.FirstOrDefault(stu => stu.Name == "hanjiu"));

  1. Single和SingleOrDefault

    相当于First()和FirstOrDefault(),但是如果不止一个匹配元素则抛出异常。

  2. 集合方法

    Count:返回集合的个数。

    Min/Max:返回集合的最小/大值。

    Sum:返回集合元素的和。

    Average:返回集合元素的平均值。

    示例代码:

int[] numbers = { 28, 32, 14 };

int fullCount = numbers .Count(); // 3

int digitCount = "pa55w0rd".Count(c => char.IsDigit(c)); // 3

int smallest = numbers.Min(); // 14;

int largest = numbers.Max(); // 32;

int smallest = numbers.Max(n => n % 10); // 8;

decimal sumTotal = numbers.Sum(); // 15

decimal average = numbers.Average(); // 5

 

本文只介绍了Linq的基本用法,尚有很多高级用法有待各位自行查阅资料进一步学习。

posted @ 2019-04-19 00:22 高原&秃鹫 阅读(...) 评论(...) 编辑 收藏

APS.NET MVC + EF (01)---Linq和Lambda表达式相关推荐

  1. SQL、Linq和Lambda表达式 的关系

    首先说说这三者完全是三种不同的东西,SQL是结构化查询语言(Structured Query Language)简称,这大家再熟悉不过了,下面主要介绍LINQ和Lambda表达式的基本概念以及同一查询 ...

  2. Db4o结合Linq、Lambda表达式的简单示例

    大多数人接触Db4o的查询,都是从"样本查询"(Query by Example)开始的,这种查询方式简单但不方便,功能和性能也很受局限.以下是引自官方的样本查询示例: // re ...

  3. Linq、Lambda表达式详细总结(转)

    (一)输入参数 在Lambda表达式中,输入参数是Lambda运算符的 左边部分.它包含参数的数量可以为0.1或者多个.只有当输入参数为1时,Lambda表达式左边的一对小括弧才可以省略.输入参数的数 ...

  4. Linq之Lambda表达式初步认识

    目录 写在前面 匿名方法 一个例子 Lambda 定义 一个例子 总结 参考文章 写在前面 元旦三天在家闲着无事,就看了看Linq的相关内容,也准备系统的学习一下,作为学习Linq的前奏,还是先得说说 ...

  5. Asp.Net MVC +EF(2)Linq查询和Lambda表达式

    Linq简介 Linq全称Language Integrated Query(语言集成查询),为我们提供一种统一的方式来查询和操作各种数据. linq to object:是针对实现IEnumerab ...

  6. sql语句-linq语言-lambda表达式对照

    1. 查询Student表中的所有记录的Sname.Ssex和Class列. select sname,ssex,class from student Linq:     from s in Stud ...

  7. lamber表达式sql_sql语句-linq语言-lambda表达式对照

    1. 查询Student表中的所有记录的Sname.Ssex和Class列.select sname,ssex,class from student Linq: from s in Students ...

  8. linq、lambda、entity framework之间的关系

    lambda: 一种匿名委托的精简版写法,明显的标志是=>符号 entity framework(简称EF): 微软访问数据库的最快捷最成熟的框架(ORM),在EF出现以前有SqlHelper. ...

  9. Linq To Sql中实现Left Join与Inner Join使用Linq语法与lambda表达式

    当前有两个表,sgroup与sgroupuser,两者通过gKey关联,而sgroup表记录的是组,而sgroupuser记录是组中的用户,因此在sgroupuser中不一定有数据.需要使用Left ...

最新文章

  1. unigui中弹出对话框原窗体是没有了_最前线 | 微信对话框“搜一搜”功能上线,独辟蹊径的腾讯打着什么算盘?...
  2. opc客户端_组态王作为OPC服务器的使用介绍,欢迎读者阅读
  3. 对Linux Kernel 4.15的支持的VirtualBox 5.2.8发布
  4. Java 11都有哪些新特性?
  5. 中国邮政编码.html,全国邮政编码一览表.doc
  6. 协同过滤算法简单实现
  7. oracle代码连接,Oracle连接核心知识点
  8. 批处理文件中获取当前所在路径的几种方法
  9. Cocos Creator 实现虚拟摇杆
  10. understand 代码解析工具的使用
  11. 使用java压缩文件成zip——三种方式压缩文件速度对比
  12. 抽象类、接口、内部类和枚举
  13. java多线程学习笔记。
  14. window下线程同步之(Event Objects(事件)) / 事件CEvent的使用
  15. linux 多线程 semaphore ,Linux下多线程编程-Pthread和Semaphore使用.doc
  16. win10安装PyPESQ库
  17. a+++a和a+a++的区别
  18. 使用Assimp库读取mtl文件数据
  19. 【解决方案】SkeyeVSS煤矿安全生产监管视频监控系统,夯实煤矿生产安全防线
  20. 关于xshell突然就连不上虚拟机的解决方法(之前可以正常连接)

热门文章

  1. 常用的一些子域名,旁站等查询网站
  2. Mysql出现问题:ERROR 1149 ( 42000 (ER_SYNTAX_ERROR)): You have an error in your SQL syntax; check th解决方案
  3. 通过省份和城市获取车籍地(车牌号码前2位)
  4. sham-link-
  5. 【HDU 1889】Reaux! Sham! Beaux!(模拟+水题)
  6. 如何为博客增加打赏功能
  7. 第2周项目3多文件组织
  8. 做完瑞吉外卖项目的一点笔记和源码
  9. Windows下安装goaccess,并支持显示中文页面的方法
  10. 用计算机算账老是出负数是怎么回事,怎样处理账务上出现存货负数的情况