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的基本用法,尚有很多高级用法有待各位自行查阅资料进一步学习。

原文地址:https://www.cnblogs.com/mrfang/p/10733513.html

时间: 2024-11-05 16:03:52

APS.NET MVC + EF (01)---Linq和Lambda表达式的相关文章

SQL、LINQ和Lambda表达式

首先说说这三者完全是三种不同的东西,SQL是结构化查询语言(Structured Query Language)简称,这大家再熟悉不过了,下面主要介绍LINQ和Lambda表达式的基本概念以及同一查询这三者的不同实现. 简单介绍 LINQ(Language Integrate Query)是语言集成查询他在对象和数据之间建立一种对应的关系,可以使用访问内存对象的方式查询数据集合.LINQ查询是C#中的一种语言构造.因此开发人员可以再C#代码汇总嵌套类似于SQL语句的查询表达式,从而实现数据查询的

C#知识体系(一) --- 常用的LInq 与lambda表达式

LinQ是我们常用的技术之一.因为我们绕不开的要对数据进行一系列的调整,如 排序. 条件筛选.求和.分组.多表联接 等等. lambda则是我们常用的语法糖,配合linq使用天衣无缝,不知不觉就用上了,主要还是看着代码简洁,逼格够高... 接下来我们就来看看常用的有哪些 先来点基础数据 //用户类 public class User { [DataMember] public int ID { get; set; } [DataMember] public string Name { get;

SQL、Linq和Lambda表达式 的关系

首先说说这三者完全是三种不同的东西,SQL是结构化查询语言(Structured Query Language)简称,这大家再熟悉不过了,下面主要介绍LINQ和Lambda表达式的基本概念以及同一查询这三者的不同实现. 简单介绍 LINQ(Language Integrate Query)是语言集成查询他在对象和数据之间建立一种对应的关系,可以使用访问内存对象的方式查询数据集合.LINQ查询是C#中的一种语言构造.因此开发人员可以再C#代码汇总嵌套类似于SQL语句的查询表达式,从而实现数据查询的

ASP.NET MVC EF 01 框架搭建

1.自动属性 (1)自动属性(Auto-Implemented Properties),C#自动属性可以避免原来我们手工的来声明一个私有成员变量以及和属性get,set的书写. public class Kencery  //声明一个Kencery的类 { public int ID{get;set;}  //主键ID public string Name{get;private set;}  //只读属性名字 public int Age{get;set;}   //年龄 } 2.隐式类型va

【2017-06-01】Linq基础+Lambda表达式实现对数据库的增删改查

一.Linq to sql 类 高集成化的数据库访问技术 使用Linq可以代替之前的Ado.Net.省去了自己敲代码的实体类和数据访问类的大量工作. 实体类: 添加一个Linq to sql 类 ----选择要使用的数据库---- 拖入要使用的表  就相当于实体类建完了. 如果进行属性扩展,在App_Code下添加类,类名同表名一致.将该类在访问修饰符后加上partial,将该类定为实体类的一部分 数据访问类: 不用在App_Code下再建数据访问类了. 直接在使用数据访问类的地方用数据库上下文

Linq之Lambda表达式初步认识

目录 写在前面 匿名方法 一个例子 Lambda 定义 一个例子 总结 参考文章 写在前面 元旦三天在家闲着无事,就看了看Linq的相关内容,也准备系统的学习一下,作为学习Linq的前奏,还是先得说说Lambda与匿名方法的知识点.也算是对知识点的查漏补缺吧,也许你会说这没啥大不了的,项目中都在用,但是有些知识,你回头在查看的时候,总会有那么点不一样的收获,这点我是感同身受的,我看书有个习惯,一本书,我能看个三四遍,每次总会有收获.当然,你可以说,当时肯定没认真看,不是那样子的,我认为最直接的原

Linq基础+Lambda表达式对数据库的增删改及简单查询

一.Linq to sql 类 高集成化的数据库访问技术 使用Linq可以代替之前的Ado.Net,省去了自己敲代码的实体类和数据访问类的大量工作 实体类: 添加一个Linq to sql 类 ----选择要使用的数据库---- 拖入要使用的表  需要立即保存 就相当于创建实体类 如果进行属性扩展,在App_Code下添加类,类名同表名一致.将该类在访问修饰符后加上partial,将该类定为实体类的一部分 数据访问类: 不用在App_Code下再建数据访问类了. 直接在使用数据访问类的地方用数据

LINQ使用Lambda表达式选择几列

学习LINQ的Lambda的表达式,尝试从数据集合中,选择其中几列. 创建一个model: source code: namespace Insus.NET.Models { public class ProdImage { public int ProductID { get; set; } public int Type { get; set; } public int Priority { get; set; } public string Url { get; set; } public

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

(一)输入参数 在Lambda表达式中,输入参数是Lambda运算符的 左边部分.它包含参数的数量可以为0.1或者多个.只有当输入参数为1时,Lambda表达式左边的一对小括弧才可以省略.输入参数的数量大于或者等于2 时,Lambda表达式左边的一对小括弧中的多个参数质检使用逗号(,)分割. 示例1 下面创建一个Lambda表达式,它的输入参数的数量为0.该表达式将显示“This is a Lambda expression”字符串. [csharp] view plaincopy ()=>Co