.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 ...
随机推荐
- 深度了解Android 7.0 ,你准备好了吗?
作者:Redyan, 腾讯移动客户端开发工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. 原文链接:http://wetest.qq.com/lab/view/288.html ...
- 初识Html:Html和CSS的关系
学习web前端开发基础技术需要掌握:HTML.CSS.JavaScript语言.下面我们就来了解下这三门技术都是用来实现什么的: 1. HTML是网页内容的载体.内容就是网页制作者放在页面上想要让用户 ...
- 一个web应用的诞生(7)--结构调整
现在所有的Py代码均写在default.py文件中,很明显这种方法下,一旦程序变的负责,那么无论对于开发和维护来说,都会带来很多问题. Flask框架并不强制要求项目使用特定的组织结构,所以这里使用的 ...
- linux下redis 集群配置
redis.conf 配置文件说明 daemonize no --是否把redis-server启动在后台,默认是“否”.若改成yes pidfile /var/run/redis.pid --当Re ...
- angular : direative : scope | 指令scope里的符号@,=
先看看以下的代码 <body ng-app="app" ng-controller="ctrl"> <dir myname="nam ...
- 每天一个linux命令(56)--crontab命令
上一节学习了 at 命令是针对仅运行一次的任务,循环运行的例行性计划任务,Linux 系统则是由 cron(crond)这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个 ...
- web前端的发展态势 浅识
以前 作为一个java程序员写的代码主要还是后台的代码,虽然开始的时候前后端都写,但是也是用别人造好的轮子来用,学学html,css,js,jquery,再找一个前端ui框架学学,上手之后我们就可以写 ...
- .NET的SqlHelper应用代码
首先需要引用命名空间 ,同时也需要右击'引用' --> '添加引用' --> '程序集' --> '框架' --> 'System.Configuration',SqlHelp ...
- 基于Spring-WS的Restful API的集成测试
在很多Java企业级应用中,Spring占据了非常重要的位置,这就导致了基本上的技术选型都是围绕着Spring来, 比方说笔者最近的项目需要开发一个Restful的API接口,选型的时候就说,客户架构 ...
- canvas作图
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...