.NET中数据访问方式(一):LINQ
语言集成查询(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 Object、LINQ to XML (C#)、LINQ to SQL、LINQ to DataSet、LINQ to Entities。LINQ to SQL
不建议使用,用LINQ to Entities
来替代。
LINQ查询包含三个步骤:
- 获取数据源
- 创建查询语句
- 执行查询
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>
类型则被编译为委托,查询结果是IQueryable
或IQueryable<T>
类型则被编译为表达式树,在运行时表达式树会被解析为适合于数据源的查询语句。
- System.Collection.Generic.IEnumerable<T>
IEnumerable
先将数据放到本地内存中,然后再执行过滤操作(如果有的话),适合于对当前进程中的数据进行查询操作,如:LINQ to XML
、LINQ to Object
。
- System.Linq.IQueryable<T>
在执行查询操作时,IQueryable
先在服务器端进行过滤操作(如果有的话),然后再将数据放到本地内存中。IQueryable
适合使用对进程外(如数据库)的数据进行查询操作,如:LINQ to Entities
。
两个命名空间
System.Linq
System.Linq命名空间中包含用于LINQ查询的类和接口
System.Linq.Expressions
System.Linq.Expressions 命名空间包含了用于创建表达式树的类、 接口。
LINQ的优缺点
优点
- 对不同的数据源提供了几乎一致的查询操作,这可使我们更多的去关注业务逻辑而非对数据源的操作
- 提供编译期的类型检查
- 在书写LINQ查询表达式时可以使用Visual Studio的智能提示
- 调试方便
缺点
- 对于复杂的查询操作显得力不从心
- 容易写出性能不高的查询表达式
结语
本篇是自己学习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的更多相关文章
- 白话LINQ系列2---以代码演进方式学习LINQ必备条件
今天,我们通过一个简单的示例代码的演进过程,来学习LINQ必备条件:隐式类型局部变量:对象集合初始化器:委托:匿名函数:lambda表达式:扩展方法:匿名类型.废话不多说,我们直接进入主题. 一.实现 ...
- 关于php中数据访问的几点补充
前几篇文章说了,parent.self.static关键字的使用,parent可以访问父类的静态方法和静态变量,self和static可以访问本类的静态成员等等,但实际上他们还有其他作用,来看一下: ...
- .NET 中数据访问用的 DBHelper(Sql Server) 类
public class DBHelper { private static string DBConnectString = "Data Source=.;Initial Catalog= ...
- DriverStudio开发PCI设备DMA数据传输
DriverWizard向导可以创建基本的wDM驱动程序框架,包括总线类型,地址空间,中断源,DMA资源,以及IOCTL(i/o控制代码)的定义等等.详细情况可参看DriverStudio的帮助文档, ...
- SharePoint—用REST方式访问列表
REST的定义与作用 在SharePoint 2010中,基本上有如下几种数据访问方式: 服务器端对象模型 LINQ to SharePoint Web Service 客户端对象模型 ADO.NET ...
- SpringBoot定时任务 - 集成quartz实现定时任务(单实例和分布式两种方式)
最为常用定时任务框架是Quartz,并且Spring也集成了Quartz的框架,Quartz不仅支持单实例方式还支持分布式方式.本文主要介绍Quartz,基础的Quartz的集成案例本,以及实现基于数 ...
- Code First开发系列之管理数据库创建,填充种子数据以及LINQ操作详解
返回<8天掌握EF的Code First开发>总目录 本篇目录 管理数据库创建 管理数据库连接 管理数据库初始化 填充种子数据 LINQ to Entities详解 什么是LINQ to ...
- 8天掌握EF的Code First开发系列之3 管理数据库创建,填充种子数据以及LINQ操作详解
本文出自8天掌握EF的Code First开发系列,经过自己的实践整理出来. 本篇目录 管理数据库创建 管理数据库连接 管理数据库初始化 填充种子数据 LINQ to Entities详解 什么是LI ...
- LINQ浅析
在C# 3.0之前,我们对不同的数据源(数据集合.SQL 数据库.XML 文档等等)进行操作(查询.筛选.投影等等),会使用不同的操作方式. C# 3.0中提出了LINQ(Language Integ ...
随机推荐
- MYSQL中添加时间
1.在创建新记录和修改现有记录的时候都对这个数据列刷新:TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 2.在创建新记录 ...
- JavaScript基础——变量、语句、注释
一.变量的命名规则 1.变量名由数字.字母.下划线组成 2.变量名的首字母不能是数字,只能是字母或者下划线 3.不能使用关键字和保留字作为变量名 4.变量严格区分大小写,例如在JavaScript中o ...
- iOS回顾笔记(03) -- 自定义View的封装和xib文件的使用详解
iOS回顾笔记(03) -- 自定义View的封装和xib文件的使用详解 iOS开发中,我们常常将一块View封装起来,以便于统一管理内部的子控件.如iOS回顾笔记(02)中的"书" ...
- 循环神经网络(RNN)模型与前向反向传播算法
在前面我们讲到了DNN,以及DNN的特例CNN的模型和前向反向传播算法,这些算法都是前向反馈的,模型的输出和模型本身没有关联关系.今天我们就讨论另一类输出和模型间有反馈的神经网络:循环神经网络(Rec ...
- 问题 : lang.NoClassDefFoundError: org/springframework/core/annotation/AnnotatedElementUtils,的解决方法
今天在做junit 测试的时候 出现了一个问题,花了一段时间 才解决. java.lang.NoClassDefFoundError: org/springframework/core/annota ...
- .NET Core 1.1日期解析无APi、SQL Server数据转换JSON
前言 在批量导入Excel中的数据时发现出生日期为整数也就是为天数,结果倒腾了翻,这是其一,其二是数据库中的某一列存的是JSON数据,但是场景是为了作为作业来运行,此时不得不将筛选出的数据手动拼接成J ...
- 基于 Koa平台Node.js开发的KoaHub.js的模板引擎代码
koahub-handlebars koahub-handlebars koahub handlebars templates Installation $ npm install koahub-ha ...
- Swiper3 的特色功能
- jump堡垒机配置使用
一.用户管理 1)添加用户 点击用户管理 —> 查看用户 —> 添加用户 输入要添加的用户名,姓名,权限,Mail,并且发送邮件 —> 保存 查看添加的用户 查看用户邮件 邮件中包含 ...
- TCP协议设计原理
TCP协议设计原理 最近去了解TCP协议,发现这是一个特别值得深思的协议.在本篇博客中,不会长篇大论的给大家介绍TCP协议特点.包头格式以及TCP的连接和断开等基本原理,而是会带大家深入理解为什么要这 ...