从查询表达式开始认识LINQ

学习和使用C#已经有2个月了,在这两个月的学习中,深刻体会到,C#这门语言还真不适合编程初学者学习 ,因为它是吸取了很多其他语言,不仅是面向对象,还包括函数式语言的很多特性,导致它变成特性大爆炸的 语言。它的许多方面单独拿出来讲,就得是一本书的规模,而且还不一定让人一下子明白。

LINQ,Language INtegrated Query,语言集成查询,是其中一个非常重要的部分,有关它的功能增强, 贯穿了整个C#的发展。

先从基本的查询表达式下手。

在讲查询表达式前,我们必须明白:查询 表达式不仅仅是针对数据库,它针对的是所有数据源,因为LINQ的意图就是为所有数据源提供统一的访问方式 。因为最近的项目使用的是LINQ to SQL,所以这里只讲LINQ to SQL。

查询表达式非常像SQL语句,但 书写方式却是反过来:

var articles = from article in db.Articles
              where a.Name == "JIM"
              select article;

我们必须明白,查询表达式返回的结果是一个序列,哪怕这个序列 只有一个元素。

正因为查询表达式返回的是一个序列,才使得它的行为非常有趣。序列的基本特点就 是每次只取一个元素,这使得每个转换都处理一个数据,而且只在结果序列的第一个元素被访问的时候才会开 始执行查询表达式。像是上面的数据流是这样的:select转换会在它返回的序列中的第一元素被访问时,为该 元素调用where转换,where转换会返回数据列表中第一个元素,检查这个谓词(a.Name == "JIM") 是否匹配,再把该元素返回给select。

这就是查询表达式的延迟执行,在它被创建的时候没有处理任 何数据,只是在内存中生成了这个查询的委托。这样子是非常高效和灵活的,但并不是所有情况都适合,像是 reverse这类的操作,就要访问整个数据源。所以,我们一般在返回另一个序列的操作中使用延迟执行,如果 是返回单一值就使用即时执行。

使用查询表达式,首先就是声明数据序列的数据源:

from article in db.Articles

where子句用来进行过滤。它会进入数据流中每个元素的谓词,只有返回true 的元素才能出现在结果序列中。我们可以使用多个where子句,只有满足所有谓词的元素才能进入结果序列。

编译器会将where子句转换为带有Lambda表达式的where方法调用,像是这样:

where(article => article.Name == "JIM")

所以我们也可以直接使用Lambda表达式,它同样是返回一 个序列:

var articles = db.Articles.Where(article => article)

使用Lambda表达式能使 我们的代码的简洁度大幅上升,这也是它为什么会被引进C#中的原因之一。

select子句就是投影,相 信学过数据库的同学一定非常熟悉。它同样也会有对应的方法调用,应该说,几乎所有的LINQ to SQL操作都 有对应的方法调用(因为编译器就是讲它们转换为方法调用),所以接下来就不再讲方法调用形式了。

前面讲过,编译器会将查询表达式转换为普通C#代码的方法调用,以select为例,它并不会像我们预期的那样 ,转换为Enumerable.Select或者List<T>.Select,它就只是对代码进行转换,然后再寻找适当方法。 该方法的参数会是一个委托类型或者一个Expression<T>。为什么转换后的方法中的参数是一个Lambda 表达式呢?因为Lambda表达式可以被转换为委托实例或者表达式树,所以使用Lambda表达式就可以对应所有情 况。这种转换并不依赖与特定类型,而只依赖与方法名称和参数,也就是所谓的动态类型(Duck Typing)的编 译时形式。

因为这样,我们可以实现自己的LINQ提供器,但除非真的有特殊需要,一般我们都不需要 做到这点。

我们来看看查询表达式中两个最重要的组成:范围变量和投影表达式。

from article in db.Articles

其中,article就是范围变量,而:

select article

投影表 达式就使用了该范围变量。编译器在转换的时候,Lambda表达式的左边,参数名称就是范围变量,右边来自于 投影表达式,所以,我们决不能这样写:

from article in db.Articles
select person

从上面来看,范围变量应该是隐式类型,编译器会自己推断它的具体类型。当然, 我们也可以使用显式类型的范围变量,像是下面这样:

from Article article in db.Articles
select article

其中,db.Articles是一个List<Article>。

这样的情况是因为我们想 要在强类型的容器中进行查询。这样的机制能够运行的保障源于一个方法:Cast()。Cast()会强制将类型转换 为目标类型,如果无法转换则会出错。

上面的表达式会转换为以下的代 码:

list.Cast<Article>().Select(article => article);

为什么需要我们对范围变 量进行显式声明呢?因为Select方法只是IEnumerable<T>的扩展方法,而不是IEnumerable,所以我们 必须要显式的声明范围变量的类型才能调用Select方法。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索查询
, 方法
, 表达式
, 序列
, article
, 一个
, 正则表达式查询
查询转换
linq 查询表达式、linq表达式、linq lambda表达式、linq 表达式树、linq 正则表达式,以便于您获取更多的相关知识。

时间: 2025-01-19 13:02:10

从查询表达式开始认识LINQ的相关文章

.Net开发必备十大工具详解之查询表达式(LINQ)

LINQ是Language Integrated Query的简称,它是集成在.NET编程语言中的一种特性.已成为编程语言的一个组成部分,在编写程序时可以得到很好的编译时语法检查,丰富的元数据,智能感知.静态类型等强类型语言的好处.并且它同时还使得查询可以方便地对内存中的信息进行查询而不仅仅只是外部数据源. LINQ定义了一组标准查询操作符用于在所有基于.NET平台的编程语言中更加直接地声明跨越.过滤和投射操作的统一方式,标准查询操作符允许查询作用于所有基于IEnumerable<T>接口的源

LINQ查询表达式基础描述

本文向大家介绍LINQ查询表达式,可能好多人还不了解LINQ查询表达式,没有关系,看完本文你肯定有不少收获,希望本文能教会你更多东西. LINQ使查询成为了.NET中头等的编程概念,被查询的数据可以是XML(LINQ to XML).Databases(LINQ to SQL.LINQ to Dataset.LINQ to Entities)和对象(LINQ to Objects).LINQ也是可扩展的,允许你建立自定义的LINQ数据提供者(比如:LINQ to Amazon.LINQ to N

C# 3.0新特性初步研究 Part6:使用查询表达式

查询表达式(Query Expression)大家都应该对SQL语句不陌生吧,在C# 2.0之前,嵌入到代码中的SQL就是下面这个样子: 1public void Test() 2{ 3SqlConnection c = new SqlConnection(-); 4  c.Open();  5  SqlCommand cmd = new SqlCommand( 6     @"SELECT c.Name, c.Phone        // queries in quotes 7       

C# 3.0语言新特性(语言规范):7 查询表达式

规范 原文:<C# Version 3.0 Specification>,Microsoft翻译:lover_P 查询表达式(Query Expression)为查询提供了一种语言集成的语法,这种语法类似于关系和分级查询语言,如SQL和XQuery. query-expression:from-clause  query-body from-clause:from  from-generators from-generators:from-generatorfrom-generators  ,

请看一个大神写的lambda表达式,不用linq请问怎么调用

问题描述 请看一个大神写的lambda表达式,不用linq请问怎么调用 Func<int, bool> MyAnd(Func<int, bool> f1, Func<int, bool> f2) { return x => f1(x) && f2(x); } 解决方案 直接调用也可以: bool b1 = MyAnd(x => x < 10, x => x % 2 == 0)(4); bool b2 = MyAnd(x =>

[Microsoft][ODBC Microsoft Access Driver] 语法错误 (逗号) 在查询表达式 &amp;amp;#x27;id = 83, 79&amp;amp;#x27; 中。

问题描述 错误类型:MicrosoftOLEDBProviderforODBCDrivers(0x80040E14)[Microsoft][ODBCMicrosoftAccessDriver]语法错误(逗号)在查询表达式'id=83,79'中./web/admin/gedanxiugai.asp,第105行修改页面代码<%varRecordset1=Server.CreateObject("ADODB.Recordset");Recordset1.ActiveConnection

各位老师帮忙看一下,为什么会出现 语法错误 (逗号) 在查询表达式这中错误呢?

问题描述 不理解的地方,第一次更新是正常,第二次更新就会提示错误代码了.如果我把浏览器记录清除,又可以了,再打开又不行了.帮忙看下哦~!万分感谢~!错误代码如下:MicrosoftOLEDBProviderforODBCDrivers(0x80040E14)[Microsoft][ODBCMicrosoftAccessDriver]语法错误(逗号)在查询表达式'id=1,1'中./Xiaofei/Mod_xf.asp,第138行代码如下:第138行的代码是:Recordset1.Open()完整

MS-SQL的子查询表达式

    1.EXISTS         EXISTS ( subquery )    EXISTS 的参数是一个任意的SELECT语句, 或者说子查询.系统对子查询进行运算以判断它是否返回行. 如果它至少返回一行,那么 EXISTS 的结果就为"真": 如果子查询没有返回行,那么 EXISTS 的结果是"假".     子查询可以引用来自周围的查询的变量,这些变量在该子查询的任何一次计算中都起常量的作用.     这个子查询通常只是运行到能判断它是否可以生成至少一

方法-关于C# link的IQueryable和IEnumerable的比较

问题描述 关于C# link的IQueryable和IEnumerable的比较 IQueryable和IEnumerable的比较,我是这么理解的,IQ是数据库查询,IE是内存查询 IQ速度快,IE速度慢,IQ不能调用自定义方法,IE可以,所以IE通用性强. 如果能用IQ就不用IE,是不是这样? 解决方案 IQueryable基于表达式树,C#遇到调用它的地方,不会直接编译这些调用代码,而是会产生一个Expression对象,用类似抽象语法树的数据结构表示查询表达式. 这样LINQ Provi