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类的实例.有了这个实例我们就可以生成对应的 ...
随机推荐
- SSH实战 · 唯唯乐购项目(上)
前台需求分析 一:用户模块 注册 前台JS校验 使用AJAX完成对用户名(邮箱)的异步校验 后台Struts2校验 验证码 发送激活邮件 将用户信息存入到数据库 激活 点击激活邮件中的链接完成激活 根 ...
- UWP开发必备:常用数据列表控件汇总比较
今天是想通过实例将UWP开发常用的数据列表做汇总比较,作为以后项目开发参考.UWP开发必备知识点总结请参照[UWP开发必备以及常用知识点总结]. 本次主要讨论以下控件: GridView:用于显示数据 ...
- CRL快速开发框架系列教程三(更新数据)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- jQuery可自动播放动画焦点图插件Koala
Koala是一款简单而实用的jQuery焦点图幻灯片插件,焦点图不仅可以在播放图片的时候让图片有淡入淡出的动画效果,而且图片可以自动播放.该jQuery焦点图的每一张图片都可以设置文字描述,并浮动在图 ...
- android 事件分发机制详解(OnTouchListener,OnClick)
昨天做东西做到触摸事件冲突,以前也经常碰到事件冲突,想到要研究一下Android的事件冲突机制,于是从昨天开始到今天整整一天时间都要了解这方面的知识,这才懂了安卓的触摸和点击事件的机制.探究如下: 首 ...
- JAVA装饰者模式(从现实生活角度理解代码原理)
装饰者模式可以动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator模式相比生成子类更为灵活. 该模式的适用环境为: (1)在不影响其他对象的情况下,以动态.透明的方式给单个对象添加职 ...
- Android 添加ActionBar Buttons
一.在res/menu文件夹下创建Xml文件 跟标签为menu,设置item <?xml version="1.0" encoding="utf-8"?& ...
- Stack Overflow 排错翻译 - Closing AlertDialog.Builder in Android -Android环境中关闭AlertDialog.Builder
Stack Overflow 排错翻译 - Closing AlertDialog.Builder in Android -Android环境中关闭AlertDialog.Builder 转自:ht ...
- Python学习基础
1.使用范围: 大数据 .图像处理.web .运维.爬虫.自动化.科学计算 2.准备环境: linux/mac python 3.5.2 ipython vim/sublime/atom 3.列表 3 ...
- 微软开源全新的文档生成工具DocFX
微软放弃Sandcastle有些年头了,微软最近开源了全新的文档生成工具DocFX,目前支持C#和VB,类似JSDoc或Sphinx,可以从源代码中提取注释生成文档之外,而且还有语法支持你加入其他的文 ...