语言集成查询(Language-Integrated Query),简称LINQ,.NET中的LINQ体系如下图所示:

 

在编程语言层次,LINQ对于不同的数据源提供了相同的查询语法,方便了程序员操作不同的数据源。

可查询类型

LINQ之所以能够使用相同的语法操作不同的数据源,是因为和LINQ直接打交道的是可查询类型而非数据源,在LINQ中,直接或间接实现了IEnumerable<T>接口的类型称为可查询类型, .NET中如:List<T>Dictionary<TKey,TValue>,数组(由CLR负责隐式实现IEnumerable<T>接口)等,实现了IEnumerable<T>接口。
IQueryable<out T>继承自IEnumerable<T>,是个标记接口。

可查询类型无需额外操作即可进行LINQ操作,若数据源在内存中不以可查询类型的形式存在,那么LINQ提供程序必须要先将数据源转换为可查询类型,如LINQ to XML将XML文件转换为可查询的XElement类型:
 XElement contacts = XElement.Load(@"c:\myContactList.xml");

LINQ 提供程序

LINQ提供程序(LINQ Provider)提供了对特定的数据源进行标准的LINQ操作及一些扩展操作(如:LINQ to XML),不同的LINQ提供程序对于一些相同名称的扩展方法会提供不同的实现方式。.NET中预定义的LINQ提供程序包括:LINQ to ObjectLINQ to XML (C#)LINQ to SQLLINQ to DataSetLINQ to Entities
LINQ to SQL不建议使用,用LINQ to Entities来替代。

LINQ查询包含三个步骤:

  1. 获取数据源
  2. 创建查询语句
  3. 执行查询

LINQ查询方式

  • LINQ 表达式(又称为查询表达式
    from关键字开头,select关键字结尾。

  • 扩展方法(又称为标准查询
    System.Linq.Enumerable类和System.Linq.Queryable类,分别针对IEnumerable<T>IQueryable<T>接口进行的扩展。.NET也提供了几个对IEnumerable和IQueryable接口进行操作的扩展方法,如: Cast<TResult>OfType<TResult>

  • LINQ 表达式和扩展方法混合使用

    (from e in Employees
    where e.Salary>
    select e).ToList()

LINQ表达式和扩展方法对比:

LINQ表达式和扩展方法在编译后的代码没有什么区别

  • 对于排序、分组、联合查询使用LINQ表达式更为方便
//以排序为例,使用年龄、姓名、邮箱进行排序,
//LINQ表达式中使用逗号分隔排序字段,而扩展方法则需要多次调用相应的扩展方法
var result= from e in Employees
where e.Age> && e.Salary>
orderby e.Age,e.Name,e.Email
select e; //等价的扩展方法
var result=Employees
.Where(e=>e.Age> && e.Salary>)
.OrderBy(e=>e.Age)
.ThenBy(e=>e.Name)
.ThenBy(e=>e.Email);
  • 扩展方法能够提供比LINQ表达式更复杂的查询
//取第26行到36行范围内的数据
var result=Employees.Skip().Take(); //使用LINQ表达式我表示写不出来......

LINQ表达式是对常用扩展方法在语法层面上的简化,LINQ表达式有着更好的可读性,在编译时LINQ表达式会被转化为对扩展方法的调用

LINQ查询特点:

  • 延迟查询
    若查询表达式的返回结果是IEnumerable<T>类型,则在声明查询表达式时不会执行查询,而是在迭代查询变量时才进行查询。贴一幅MSDN上的经典LINQ查询流程图(延迟查询):

     
  • 立即查询
    若查询表达式返回单个值或者使用了ToList<T>ToArray<T>等方法时会执行立即查询,因为这些操作会遍历数据。

一句话总结,若查询表达式不包含对数据源的遍历操作则执行延迟查询,否则会进行立即查询

LINQ表达式中的查询关键字

表格中的英文没什么难点,就不翻译了 :)

关键字 描述
from Specifies a data source and a range variable (similar to an iteration variable).
where Filters source elements based on one or more Boolean expressions separated by logical AND and OR operators.
select Specifies the type and shape that the elements in the returned sequence will have when the query is executed.
group Groups query results according to a specified key value.
into Provides an identifier that can serve as a reference to the results of a join, group or select clause.
orderby Sorts query results in ascending or descending order based on the default comparer for the element type.
join Joins two data sources based on an equality comparison between two specified matching criteria.
let Introduces a range variable to store sub-expression results in a query expression.
in Contextual keyword in a join clause.
on Contextual keyword in a join clause.
equals Contextual keyword in a join clause.
by Contextual keyword in a group clause.
ascending Contextual keyword in an orderby clause.
descending Contextual keyword in an orderby clause.

两个接口

在LINQ中,一个查询表达式被编译为表达式树或者委托,查询结果为IEnumerable<T>类型则被编译为委托,查询结果是IQueryableIQueryable<T>类型则被编译为表达式树,在运行时表达式树会被解析为适合于数据源的查询语句。

  • System.Collection.Generic.IEnumerable<T>
    IEnumerable先将数据放到本地内存中,然后再执行过滤操作(如果有的话),适合于对当前进程中的数据进行查询操作,如:LINQ to XMLLINQ to Object
  • System.Linq.IQueryable<T>
    在执行查询操作时,IQueryable先在服务器端进行过滤操作(如果有的话),然后再将数据放到本地内存中。
    IQueryable适合使用对进程外(如数据库)的数据进行查询操作,如:LINQ to Entities

两个命名空间

System.Linq

System.Linq命名空间中包含用于LINQ查询的类和接口

System.Linq.Expressions

System.Linq.Expressions 命名空间包含了用于创建表达式树的类、 接口。

LINQ的优缺点

优点

  1. 对不同的数据源提供了几乎一致的查询操作,这可使我们更多的去关注业务逻辑而非对数据源的操作
  2. 提供编译期的类型检查
  3. 在书写LINQ查询表达式时可以使用Visual Studio的智能提示
  4. 调试方便

缺点

  1. 对于复杂的查询操作显得力不从心
  2. 容易写出性能不高的查询表达式

结语

本篇是自己学习LINQ的总结,不求面面俱到。通篇以文字叙述为主,辅以少量代码,若有错误希望大家指出。

工具推荐

LINQ Pad是一款轻量级的数据查询工具,在LINQ Pad中可以使用LINQ表达式、扩展方法、SQL语句等对数据库进行操作,简单易用功能强大。

书目推荐:

《LINQ Interview Questions Answers》

参考文章

Introduction to LINQ Queries (C#)
Standard Query Operators Overview (C#)
Query Expression Syntax for Standard Query Operators (C#)
Data Transformations with LINQ (C#)
LINQ provider basics
Enabling a Data Source for LINQ Querying
LINQ: Building an IQueryable Provider – Part I

版权声明

本文为作者原创,版权归作者雪飞鸿所有。 转载必须保留文章的完整性,且在页面明显位置处标明原文链接

如有问题, 请发送邮件和作者联系。

.NET中数据访问方式(一):LINQ的更多相关文章

  1. 白话LINQ系列2---以代码演进方式学习LINQ必备条件

    今天,我们通过一个简单的示例代码的演进过程,来学习LINQ必备条件:隐式类型局部变量:对象集合初始化器:委托:匿名函数:lambda表达式:扩展方法:匿名类型.废话不多说,我们直接进入主题. 一.实现 ...

  2. 关于php中数据访问的几点补充

    前几篇文章说了,parent.self.static关键字的使用,parent可以访问父类的静态方法和静态变量,self和static可以访问本类的静态成员等等,但实际上他们还有其他作用,来看一下: ...

  3. .NET 中数据访问用的 DBHelper(Sql Server) 类

    public class DBHelper { private static string DBConnectString = "Data Source=.;Initial Catalog= ...

  4. DriverStudio开发PCI设备DMA数据传输

    DriverWizard向导可以创建基本的wDM驱动程序框架,包括总线类型,地址空间,中断源,DMA资源,以及IOCTL(i/o控制代码)的定义等等.详细情况可参看DriverStudio的帮助文档, ...

  5. SharePoint—用REST方式访问列表

    REST的定义与作用 在SharePoint 2010中,基本上有如下几种数据访问方式: 服务器端对象模型 LINQ to SharePoint Web Service 客户端对象模型 ADO.NET ...

  6. SpringBoot定时任务 - 集成quartz实现定时任务(单实例和分布式两种方式)

    最为常用定时任务框架是Quartz,并且Spring也集成了Quartz的框架,Quartz不仅支持单实例方式还支持分布式方式.本文主要介绍Quartz,基础的Quartz的集成案例本,以及实现基于数 ...

  7. Code First开发系列之管理数据库创建,填充种子数据以及LINQ操作详解

    返回<8天掌握EF的Code First开发>总目录 本篇目录 管理数据库创建 管理数据库连接 管理数据库初始化 填充种子数据 LINQ to Entities详解 什么是LINQ to ...

  8. 8天掌握EF的Code First开发系列之3 管理数据库创建,填充种子数据以及LINQ操作详解

    本文出自8天掌握EF的Code First开发系列,经过自己的实践整理出来. 本篇目录 管理数据库创建 管理数据库连接 管理数据库初始化 填充种子数据 LINQ to Entities详解 什么是LI ...

  9. LINQ浅析

    在C# 3.0之前,我们对不同的数据源(数据集合.SQL 数据库.XML 文档等等)进行操作(查询.筛选.投影等等),会使用不同的操作方式. C# 3.0中提出了LINQ(Language Integ ...

随机推荐

  1. Asp.Net MVC学习总结(二)——控制器与动作(Controller And Action)

    一.理解控制器 1.1.什么是控制器 控制器是包含必要的处理请求的.NET类,控制器的角色封装了应用程序逻辑,控制器主要是负责处理请求,实行对模型的操作,选择视图呈现给用户. 简单理解:实现了ICon ...

  2. 关于select count

    关于select count,之前有一些不清楚的地方,看到阿里巴巴的Java编程规范,sql规约的第一条就是关于select count的 需要明确以下两点: 1.select count(常量)和s ...

  3. 快速排序OC、Swift版源码

    前言: 你要问我学学算法在工作当中有什么用,说实话,当达不到那个地步的时候,可能我们不能直接的感觉到它的用处!你就抱着这样一个心态,当一些APP中涉及到算法的时候我不想给其他人画界面!公司的项目也是暂 ...

  4. Redis简单配置和使用

    学到Redis中需要整理和配置的东西比较多,资源也是比较分散!这次的主要还是将知识整合一下,开发过程中所需要的资源整合一下,也方便今后涉及到这块地方的知识时,将时间大量浪费在了找这些资源上了! 一.R ...

  5. Android网络开发实例(基于抓包实现的网络模拟登录,登出和强制登出)

    学习Android有几个月了,最近喜欢上了网络编程,于是想通过Android写一些一个小程序用于连接外网.在这里非常感谢雪夜圣诞的支持,非常感谢,给我打开新的一扇门. 1.声明,本程序只能用于西南大学 ...

  6. ABP入门系列(13)——Redis缓存用起来

    ABP入门系列目录--学习Abp框架之实操演练 源码路径:Github-LearningMpaAbp 1. 引言 创建任务时我们需要指定分配给谁,Demo中我们使用一个下拉列表用来显示当前系统的所有用 ...

  7. 玩转 iOS 10 推送 —— UserNotifications Framework(合集)

    iOS 10 came 在今年 6月14号 苹果开发者大会 WWDC 2016 之后,笔者赶紧就去 apple 的开发者网站下载了最新的 Xcode 8 beta 和 iOS 10 beta,然后在自 ...

  8. 在Windows平台搭建轻巧的Python开发环境——面向工程和科研的扩展包配置

    首先,下载最新版本的Python. 为什么强调最新版本呢,因为新版本的漏洞通常会少得多,而且反映了未来的趋势. 既然要学,何不起点高一点? 官方下载地址:https://www.python.org/ ...

  9. Memcached 内存管理详解

    Memcached是一个高效的分布式内存cache,了解memcached的内存管理机制,便于我们理解memcached,让我们可以针对我们数据特点进行调优,让其更好的为我所用. 首先需要我们先了解两 ...

  10. 在.NET项目中使用PostSharp,使用MemoryCache实现缓存的处理(转)

    在之前一篇随笔<在.NET项目中使用PostSharp,实现AOP面向切面编程处理>介绍了PostSharp框架的使用,试用PostSharp能给我带来很多便利和优势,减少代码冗余,提高可 ...