谈谈C#使用Linq进行查询操作

前言

距离上一次更新,已经过去了一周,说起来实在是有些惭愧。一方面,近日的工作的重心在于前端api这块,没有时间精力再去补充C#的相关知识,另一方面,感觉学习的劲头确实不如从前了,近日提笔,也算是一种反思惊醒。今日整理的Linq知识,也是我一直想整理的,尤其在遇到EFcore进行联合查询的时候就遇到了linq,于是便有了下文。

本文整理转载于博客园:https://www.cnblogs.com/dotnet261010/p/8278793.html

知乎:https://zhuanlan.zhihu.com/p/29049086

什么是linq以及为什么使用linq?

长期以来,开发社区形成以下的格局:

1、面向对象与数据访问两个领域长期分裂,各自为政。

2、编程语言中的数据类型与数据库中的数据类型形成两套不同的体系,例如:

  C#中字符串用string数据类型表示。

  SQL中字符串用NVarchar/Varchar/Char数据类型表示。

3、SQL编码体验落后

  没有智能感知效果。

  没有严格意义上的强类型和类型检查。

4、SQL和XML都有各自的查询语言,而对象没有自己的查询语言。

上面描述的问题,都可以使用LINQ解决,那么究竟什么是LINQ呢?

LINQ(Language Integrated Query)即语言集成查询。

LINQ是一组语言特性和API,使得你可以使用统一的方式编写各种查询。用于保存和检索来自不同数据源的数据,从而消除了编程语言和数据库之间的不匹配,以及为不同类型的数据源提供单个查询接口.

LINQ总是使用对象,因此你可以使用相同的查询语法来查询和转换XML、对象集合、SQL数据库、ADO.NET数据集以及任何其他可用的LINQ提供程序格式的数据。

LINQ主要包含以下三部分:

1、LINQ to Objects      主要负责对象的查询。

2、LINQ to XML           主要负责XML的查询。

3、LINQ to ADO.NET   主要负责数据库的查询。

  LINQ to SQL

  LINQ to DataSet

  LINQ to Entities

 

使用LINQ的优势

1、熟悉的语言:开发人员不必为每种类型的数据源或数据格式学习新的语言。

2、更少的编码:相比较传统的方式,LINQ减少了要编写的代码量。

3、可读性强:LINQ增加了代码的可读性,因此其他开发人员可以很轻松地理解和维护。

4、标准化的查询方式:可以使用相同的LINQ语法查询多个数据源。

5、类型检查:程序会在编译的时候提供类型检查。

6、智能感知提示:LINQ为通用集合提供智能感知提示。

7、整形数据:LINQ可以检索不同形状的数据。

Linq的操作语法

总的来说,LINQ查询时有两种语法可供选择:查询表达式语法(Query Expression)和方法语法(Fluent Syntax)。

一、查询表达式语法

查询表达式语法是一种更接近SQL语法的查询方式。

LINQ查询表达式语法如下:

1 from<range variable> in <IEnumerable<T> or IQueryable<T> Collection>
2 <Standard Query  Operators> <lambda expression>
3 <select or groupBy operator> <result   formation>
约束LINQ查询表达式必须以from子句开头,以select或group子句介绍
关键字功能
from....in...

指定要查询的数据源以及范围变量,多个from子句则表示从多个数据源查找数据。注意:C#编译器会把“复合from子句”的查询表达式转换为SelectMany()扩展方法。

join…in…on…equals…指定多个数据源的关联方式
let引入用于存储查询表达式中子表达式结果的范围变量。通常能达到层次感会更好,使代码更易于阅读。
orderby、descending指定元素的排序字段和排序方式。当有多个排序字段时,由字段顺序确定主次关系,可指定升序和降序两种排序方式
where指定元素的筛选条件。多个where子句则表示了并列条件,必须全部都满足才能入选。每个where子句可以使用谓词&&、||连接多个条件表达式。
group指定元素的分组字段。
select指定查询要返回的目标数据,可以指定任何类型,甚至是匿名类型。(目前通常被指定为匿名类型)
into 

提供一个临时的标识符。该标识可以引用join、group和select子句的结果。

1)        直接出现在join子句之后的into关键字会被翻译为GroupJoin。(into之前的查询变量可以继续使用)

2)        select或group子句之后的into它会重新开始一个查询,让我们可以继续引入where, orderby和select子句,它是对分步构建查询表达式的一种简写方式。(into之前的查询变量都不可再使用)

查询语法从一个From子句开始,然后是一个Range变量。 From子句的结构类似于“From rangeVariableName in IEnumerablecollection”。 在英语中,这意味着,从集合中的每个对象。 它类似于foreach循环:foreach(student in studentList)。

在From子句之后,您可以使用不同的标准查询运算符来过滤,分组,连接集合的元素。 LINQ中有大约50个标准查询运算符。标准查询运算符后面通常跟一个条件,这个条件通常使用lambda表达式来表示。

LINQ查询语法总是以Select或Group子句结束。 Select子句用于对数据进行整形。 您可以选择整个对象,因为它是或只有它的一些属性。 在上面的例子中,我们选择了每个结果字符串元素。

例如:我们要从数组中查询出偶数,查询表达式示例代码如下:

var result = from p in ints where p % 2 == 0 select p;

查询表达式语法要点总结:

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

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

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

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

Linq的Lambda表达式

通常情况下,Lambda表达式与LINQ查询一起使用。枚举静态类包括接受Func <TSource,bool>的IEnumerable <T>的Where扩展方法。IEnumerable <Int>集合的Where()扩展方法需要传递Func <Student,bool>,如下所示:

现在,您可以将分配给Func委托的lambda表达式传递给方法语法中的Where()扩展方法,如下所示:

Func<int, bool> isContains = p =>p.Equals (4);
2 int[] ints = { 5, 2, 0, 66, 4, 32, 7, 1 };
3 var result = ints.Where(isContains).ToList();

Linq查询表达式总结

●join子句:连接多个用于查询操作的数据源。

例如:

int[]arr =new int[]{0,1,2,3,4,5,6,7,8,9};
var query1=from n in arr  
                select n;
var query2=from n in arr  
              where n >6  
              select n;

2.From字句

from子句用来指定查询表达式的数据源和范围变量。它是查询表达式的必有部分,并且它出现在最开始。数据源不但可以包括查询本身的数据源,而且还可以包括子查询的数据源。范围变量用来表示数据源序列中的每一个元素。

注意:from子句指定的数据源的类型必须为IEnumerable,IEnumerable<T>或一种派生类型。

在查询表达式中,from子句至少有一个,只有一个from的查询表达式称为单个from子句表达式。上面的query1和query2都是这类。

另一种类型叫做包含多个from子句的查询表达式,例子如下:

int[] arr1= new int[] {0,1,2,3,4,5,6,7,8,9};  
int[] arr2=new int[] {0,1,2,3,4,5,6,7,8,9};  
var query =from a in arr1  
       from b in arr2  
       select a +b; 

查询同一个数据源的例子:

public class UserInfo 
{  
    Public string Name;  
    Public List<string> AliasName;  
} 
List<UserInfo> list =...  
var query =from u in list  
     from name in u.AliasName  
     select u.Name+name; 

3.Select 子句

select子句用来指定将在执行查询时产生的值的类型。查询表达式必须以select子句或group子句结束。

如果我们继续使用上面的类UserInfo:

每个对象的ID都是一个UserInfo型的对象,Name是这个对象的Name

4.Where子句

where子句用来指导将在查询表达式中返回数据源中的哪些元素。它将一个布尔条件应用于数据源中的每个元素,并返回指定条件的元素。查询表达式可以包含一个或多个where子句。

int[] arr =new int[] {0,1,2,3,4,5,6,7,8,9};  
var query =from n in arr  
        where n <3 && n >0  //使用&&或者||分隔多个where 条件
        select n; 

甚至可以在where子句中使用返回布尔型的方法:

5.Let子句

let子句用来创建一个新的范围变量,它用于存储子表达式的结果。let子句使用编程者提供的表达式的结果初始化该变量。一旦初始化了该范围变量的值,它就不能用于存储其他的值。

例如:

就可以找到所有由元音字幕开头的单词了

6. orderby子句

orderby子句可使返回的查询结果按升序或者降序排序。升序由关键字ascending指定,而降序由关键字descending指定。

注意:orderby子句默认排序方式为升序。

orderby子句可以包含一个或多个排序表达式,各个排序表达式使用逗号(,)分隔。

例如:

int[] arr =new int[]{0,1,2,3,4,5,6,7,8,9};  
var query =from n in arr  
        where n>1 && n<6  
        orderby n descending  
        select n ; 

7.groupby子句

group子句用来将查询结果分组,并返回一对象序列。这些对象包含零个或更多个与改组的key值匹配的项,还可以使用group子句结束查询表达式。

注意:每一个分组都不是单个元素,而是一个序列(也属于集合)。

如果我们执行一下,会发现结果其实是分成两组的:

我们可以调用如下方式去查看每个组的key和里面元素的数目:

结果如下:

IGrouping<TKey, TElement> 的键表示 IGrouping<TKey, TElement> 中的每个值所共有的属性。

8.into子句

into子句可以用来创建一个临时标识符,将group、join或select子句的结果存储到这个标识符中。

            int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            var query = from n in arr
                        where n > 1 && n < 7
                        group n by n % 2 into g
                        from sn in g
                        select sn;
            Console.WriteLine(query.Count()); //结果是5
            //结果是2 4 6 3 5
            foreach (int i in query) {
                Console.WriteLine(i);
            }

9.join子句

join子句用来连接两个数据源,即设置两个数据源之间的关系。join子句支持以下3种常见联接方式。

9.1 内部连接

join子句的内部联接要求两个数据源都必须存在相同的值,即两个数据源都必须存在满足联接关系的元素,类似于SQL的inner join。

示例1

join b in arrb on a equals b: 将arra和arrb数组进行联接,同时满足a和b相等的条件。其中,b元素是arrb数组中的元素。

9.2 分组连接

join子句的分组联接包含into子句的join子句的链接。它将左数据源与右数据源的元素一次匹配。左数据源的所有元素都出现在查询结果中。若在右数据源中找到匹配项,则使用匹配的数据,否则用空表示。

9.3 左外部连接

join子句的左外部链接将返回左侧数据源序列中的所有元素,就算它们在右侧序列中没有匹配的元素也是。

 

 

 

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值