LinqToDB 源码分析——设计原理
我们知道实现了IQueryable<T>接口和IQueryProvider接口就可以使用Linq To SQL的功能。关于如何去实现的话,上一章也为我们引导了一个方向。LinqToDB框架也是顺着这个方向进行的。然而笔者对LinqToDB框架的作者真的很无语。如果有打开过LinqToDB框架源码的朋友,可能会发现很多代码都没有文字说明。这无疑给那些想要深入了解框架的人加大了前进力度。本来笔者以为只是没有相关代码说明不用怕。只要找到对应的文档应该没有什么大问题。于是笔者也跟很多人一样子——去作者的github上找。结果只有教大家如何使用。却对框架没有进行任何说明。笔者又想也许作者比较懒吧。可能只有在他的博客上才有相关的文档吧。结果笔者很失望——没有找到任何有帮助的东西。唉!为了能获得更多的资料笔者还购买了VPN。所以想要了解LinqToDB框架只有一个方式——硬着头皮啃代码。显然这种做法就是从代码中寻找作者的思路和理念。同时不可否认存在猜测上的错误。必竟作者的随意一段代码就有可能导至理解上的误导。希望读者们能够理解。
LinqToDB框架的原理
正如上面所讲的,LinqToDB框架也是按上一章中讲到的三个大至步骤进行的。所以我们的目标也变得很明确——了解LinqToDB框架是如何实现这三大步骤的。
1.实现Linq提供的IQueryable<T>接口和IQueryProvider接口。生成相关的表达式树。
2.把对应的表达式树转化生成对应数据库的SQL语句。并执行。
3.根据映射的信息,生成对应的集合类。
从上一章的例子中我们可以看到LinqToDB框架以DataContext类作为入口类。这一点显然跟Entity Framework一样子。都是以某个类做为上下文引动整个框架。如果你们看过github上的例子的话,就会发现笔者用的入口类跟作者不太一样子。作者用的是DataConnection类。事实上不管是DataConnection类还是DataContext类他们都继承了IDataContext接口。所以在使用上来讲,不会差太多。只是在笔者看来他们之间的职责却存在很大的差别。不过笔者还是不太明白作者这样子设计的目的。DataConnection类能做DataContext类的大部分事情,却又拥有自己独有的职责——负责存取当前数据库的信息。让笔者感觉DataConnection类在职责上有一点重复了。这也是为什么笔者认为DataContext类才是LinqToDB框架入口类。至少让笔者觉得DataContext类比较明确。

上面这张图片是描述了LinqToDB框架在查询时候的一个原理图。是笔者根据代码的运行路线整理出来的。主要的目地就是为了方便导引大家深入,少走一点弯路。我们知道要实现Linq查询很简单,就是上面的三个步骤。可是要实现这三个步骤的事情却很多。图片上只是显示主要核心类切口。可以说这三个步骤就是靠图片上的类进行工作的。
加载数据数库信息
LinqToDB框架并没有直接就将实现IQueryable<T>和IQueryProvider的类交出来。而是以上下文的思维方式间接性的引导出来。这也是合理的设计。必竟在生成表达式树和SQL语句之前,我们有必要知道数据库的相关信息。比如当前数据库是用什么——Sql Server还是MySql。而这个工作任务交给图中的DataConnection。这味意着LinqToDB框架在进入上面所讲的第一步的时候,就已经知道数据库的信息了。但是作者并没有直接性的设置数据库的信息。而是通过IDataProvider接口实例来提供。这样子更加区别出DataContext类只是用于引导的职责。如果你们使用过增删改的话,你们可能会觉得不对。他不是可以会增删改吗?事实上如果你们用心点的话,就会现他们都是静态扩展方法。
生成表达式树
通过DataContext类我们就可以拿到我们的集合表(这里的集合表是指实现ITable接口的实例)。ITable接口作用跟Entity Framework的IDbSet接口很相近。从代码中我们可能看到他来自于IExpressionQuery接口。相信大家看到名字就明白IExpressionQuery接口的实现类就是图片中的ExpressionQuery类。这个时候上面说的第一步工作开始进行了。ExpressionQuery类就是对应的实现IQueryable<T>接口和IQueryProvider接口的类。当然,LinqToDB框架用的是IQueryable<T>接口的子接口——IOrderedQueryable<T>。生成表达式树的工作也在这里进展开始了。
执行数据库
要实现Linq查询的功能主要难点在如何去处理表达式树,在通过表达式树生成对应的T-SQL。LinqToDB框架通过一个核心类Query来作中间过度。笔者喜欢把他叫中间者。作者在设计用到Query类时候,并不是把他直接实例出来。而是通过ExpressionBuilder类进行进一步的加工,把相关的信息分配来Query类实例,在返回Query类实例。那么对于ExpressionBuilder类的职责笔者用一俩句话是很难说清楚。这里只能大概讲他是用于处理表达式树的。其中不得不用到一个叫SelectQuery类的。这个类很重要。他会参与最后生成T-SQL工作里面去。笔者想说通过ExpressionBuilder类加工之后,对应的是查询还是增删改都会记录在SelectQuery类实例里面。就相当于生成T-SQL的信息都存放在SelectQuery类实例里面。
Query类的工作职责比较复杂。当经历过处理表达式树的过程之后,Query类就具备生成T-SQL的能力了。为什么这样子讲呢?这个时候Query类拥有生成T-SQL的SelectQuery类实例和结果集的映射信息MapInfo类实例。所以生成T-SQL也只是一个时间问题。在生成T-SQL的这个过程看起来简单,事实上却有很多细节要处理。作者让LinqToDB框架通过DataConnection类去调用BasicSqlBuilder类的子类来处理生成T-SQL。当然这一个过程里面离不开SelectQuery类。只是作者并不是直接提交T-SQL,而是生成一个叫PreparedQuery类实例。PreparedQuery类用于存放执行数据库的信息。这也是最后一步了。通过PreparedQuery类实例生成XxxCommand类执行数据库。在通过MapInfo类实例转化为对应的集合数据。
结束语
好了。对于LinqToDB框架的原理笔者就介绍在这里。本系列的后面章节也是依据本章的思路进行的。看看作者是什么样子设计LinqToDB框架的。又有什么值得我们去学习的。
LinqToDB 源码分析——设计原理的更多相关文章
- LinqToDB 源码分析——生成表达式树
当我们知道了Linq查询要用到的数据库信息之后.接下就是生成对应的表达式树.在前面的章节里面笔者就已经介绍过.生成表达式树是事实离不开IQueryable<T>接口.而处理表达式树离不开I ...
- Tomcat源码分析——请求原理分析(上)
前言 谈起Tomcat的诞生,最早可以追溯到1995年.近20年来,Tomcat始终是使用最广泛的Web服务器,由于其使用Java语言开发,所以广为Java程序员所熟悉.很多人早期的J2EE项目,由程 ...
- MyBatis 源码分析 - 缓存原理
1.简介 在 Web 应用中,缓存是必不可少的组件.通常我们都会用 Redis 或 memcached 等缓存中间件,拦截大量奔向数据库的请求,减轻数据库压力.作为一个重要的组件,MyBatis 自然 ...
- Spring Boot 揭秘与实战 源码分析 - 工作原理剖析
文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoCo ...
- Tomcat源码分析——请求原理分析(下)
前言 本文继续讲解TOMCAT的请求原理分析,建议朋友们阅读本文时首先阅读过<TOMCAT源码分析——请求原理分析(上)>和<TOMCAT源码分析——请求原理分析(中)>.在& ...
- Tomcat源码分析——请求原理分析(中)
前言 在<TOMCAT源码分析——请求原理分析(上)>一文中已经介绍了关于Tomcat7.0处理请求前作的初始化和准备工作,请读者在阅读本文前确保掌握<TOMCAT源码分析——请求原 ...
- wifidog源码分析 - wifidog原理 tiger
转:http://www.cnblogs.com/tolimit/p/4223644.html wifidog源码分析 - wifidog原理 wifidog是一个用于配合认证服务器实现无线网页认证功 ...
- Struts2 源码分析-----工作原理分析
请求过程 struts2 架构图如下图所示: 依照上图,我们可以看出一个请求在struts的处理大概有如下步骤: 1.客户端初始化一个指向Servlet容器(例如Tomcat)的请求: 2.这个请求经 ...
- LinqToDB 源码分析——生成与执行SQL语句
生成SQL语句的功能可以算是LinqToDB框架的最后一步.从上一章中我们可以知道处理完表达式树之后,相关生成SQL信息会被保存在一个叫SelectQuery类的实例.有了这个实例我们就可以生成对应的 ...
随机推荐
- [.NET] 打造一个很简单的文档转换器 - 使用组件 Spire.Office
打造一个很简单的文档转换器 - 使用组件 Spire.Office [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6024827.html 序 之前,& ...
- 【原创经验分享】WCF之消息队列
最近都在鼓捣这个WCF,因为看到说WCF比WebService功能要强大许多,另外也看了一些公司的招聘信息,貌似一些中.高级的程序员招聘,都有提及到WCF这一块,所以,自己也关心关心一下,虽然目前工作 ...
- C#向PPT文档插入图片以及导出图片
PowerPoint演示文稿是我们日常工作中常用的办公软件之一,而图片则是PowerPoint文档的重要组成部分,那么如何向幻灯片插入图片以及导出图片呢?本文我将给大家分享如何使用一个免费版Power ...
- [原] KVM 虚拟化原理探究(4)— 内存虚拟化
KVM 虚拟化原理探究(4)- 内存虚拟化 标签(空格分隔): KVM 内存虚拟化简介 前一章介绍了CPU虚拟化的内容,这一章介绍一下KVM的内存虚拟化原理.可以说内存是除了CPU外最重要的组件,Gu ...
- servlet 简介,待完善
什么是Servlet?① Servlet就是JAVA 类② Servlet是一个继承HttpServlet类的类③ 这个在服务器端运行,用以处理客户端的请求 Servlet相关包的介绍--javax. ...
- isEmpty和isNull()区别
isEmpty和isNull()区别一个NULL字符串一定是一个空串,一个空串未必是一个NULL字符串例如:QString().isNull(): //结果为trueQString().isEm ...
- Android 算法 关于递归和二分法的小算法
// 1. 实现一个函数,在一个有序整型数组中二分查找出指定的值,找到则返回该值的位置,找不到返回 -1. package demo; public class Mytest { public st ...
- Git使用详细教程(二)
分支 其实在项目clone下来后就有一个分支,叫做master分支.新建分支的步骤:右键项目→Git→Repository...→Branches... master分支应该是最稳定的,开发的时候,建 ...
- git多账号登录问题
作者:白狼 出处:http://www.manks.top/git-multiply-accounts.html 本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文 ...
- 记:MySQL 5.7.3.0 安装 全程截图
前言: 下一个班快讲MySQL数据库了,正好把服务器里面的MySQL卸了重装了一下. 截个图,作为笔记.也正好留给需要的朋友们. 目录: 下载软件 运行安装程序 安装程序欢迎界面 许可协议 查找更新 ...