我的ORM之十-- MyOql实现原理

时间:2022-04-10 01:21:48

我的ORM索引

ORM的功能

两个基本功能

  • 翻译:对象查询转化为SQL
  • 映射:把查询结果转化为实体

更多功能

如果仅仅实现这两个功能,那这两个是可以独立的,实现起来也就很简单了。但MyOql的目标还有以下部分:

  • 缓存:通过配置文件,在运行时配置缓存。数据变更后(包含存储过程执行后的数据变更),自动破坏缓存对象。
  • 分库:把某些表指向其它的数据库
  • 分表:按一定规则,把数据拆到不同的表。这些不同的表也可以部署在不同的服务器上。MyOql叫变表。
  • 权限:在用户查询时,根据用户角色,可以对表数据进行验证。
  • 对表进行分组。目前只是一级分组,不能多级分组。
  • 对列枚举化。
  • 使MyOql读起来像SQL。
  • 最大程度贴近SQL的最大实现范围。可以执行存储过程、表值函数、标量函数、系统函数、Case When、With As、分页、聚合函数。

对ORM的要求

要实现这些功能,MyOql需要做到:

  • 识别用户操作:是对哪个表进行了哪些操作。不能漏。
  • 执行前事件:在对象转化为SQL之前,先对操作事件进行验证控制。
  • 执行后事件:如果数据是变更,去破坏缓存对象。
  • 取连接事件:控制分库。
  • 取表名事件:控制分表。

因为要控制用户操作,所以在MyOql的系统中,不能使用SQL!这是MyOql 和其它ORM的区别!所以MyOql设计的很灵活,可以实现任何操作(实在特殊的存储过程接着)

MyOql实现的对象翻译Sql机制

MyOql定义了以下几个动作,在这些动作中,保存着各种数据:

  • Select
  • Update
  • Insert
  • Delete
  • BatchInsert
  • BatchUpdate
  • Proc

在翻译的时候,只要识别这些子句就OK了。其它一些很灵活的数据,我为了方便,并没有专门定义属性,而是放到了 Dna 属性里。 在翻译的时候,去Dna里查找就OK了。

如:

Select是最复杂的动作,Select动作的Dna里就包含了: 显示列,Where子句,Join子句,OrderBy子句,GroupBy子句,having子句。

Update动作的Dna里包含了: 更新实体,Where条件,关联表(多表更新)

Insert动作的Dna里包含了:插入实体,Select子句(可以执行 Insert table(列) select (列) from table2)。

Delete是最简单的动作,仅包含一个Where就可以。

这样的机制是尽量的遵循SQL的写法,而没有对写法进行强制约束,比如,你可以这样写:

dbr.Menu.Select().Where(dbr.PUser.Id > ).ToScalar();

它也可以编译成功,生成的SQL是:

select * from Menu where User.Id > 1

Lambda的支持是为了尽量的约束以上不规范的地方:

dbr.Menu.Select().Where(o => o.Id > ).ToScalar();

此时Where的参数是 Func<MenuRule,WhereClip> , o 就表示 Menu 表,程序员在写的时候,就不会写到User表里了。

基于以上动作,MyOql可以识别程序对哪些表进行了何种操作。就可以对各个时机进行控制了。

映射

这个没什么好说的,哪个快用哪个。目前使用的是 FastReflectionLib,基于Emit。总之比反射快。

缓存

缓存一直是MyOql的重点,优其是缓存破坏!

缓存数据并不困难,在数据发生变更时,破坏关联的缓存数据才是最最重要的。

MyOql在生成实体时,会从存储过程中分析出该存储过程用到了哪些表,调用了哪些存储过程(递归找出使用的表),建立 存储过程对表的依赖(哪位同学有更好的算法,请指教。我目前是用正则从源码中找的,可能不准),在执行存储过程时,把该存储过程的依赖表的关联缓存项清掉。

理论上可以对简单视图进行写操作,但是为了规范化,视图主要是用来查询的,我在视图的接口上禁用了写操作。

按ID查询流程

  • dbo.Event.OnReading
  • MyOqlCacheManager.GetFromCacheById
  • ToCommand
  • dbo.SetLastQueryedResult
  • MyOqlCacheManager.SetCache
  • dbo.Event.OnReaded

按SQL查询流程

  • dbo.Event.OnReading
  • 如果页数太靠后,则把排序倒置,把页数倒排。如果是第一页并有Take数,则进行总数查询。
  • ToCommand
  • MyOqlCacheManager.GetFromCacheBySql
  • dbo.SetLastQueryedResult
  • MyOqlCacheManager.SetCache
  • dbo.Event.OnReaded

MyOqlCacheManager.GetFromCacheByXXX

取缓存时,可能会从远程服务器读取,为了进行优化,实现以下流程:

本地保存远程服务器的缓存Key,如果本地保存着远程的缓存Key,则进行查询,如果远程查不到,则删除本地缓存Key项。

变表

如果数据库表定义了大括号,MyOql会认为它是变表。 如: T_Fees_{CorpID},它是变表模板,在生成表名的时候,我会用 CorpID 这个变量,来替换=》 T_Fees_{1} , T_Fees_{2} 表示1号公司的收费表,2号公司的收费表,我们称它为分表。

变表需要在某个时机,根据变表模板生成分表。 如创建新公司信息的时候,就把该公司的收费表创建好。

在理解了以上部分之后,参考示例,其它的也就很好理解了。

我的ORM之十-- MyOql实现原理的更多相关文章

  1. Linux学习之CentOS&lpar;二十八&rpar;--RAID原理基础及Linux下软件RAID配置

    一.RAID的原理基础 在 讲解RAID的原理基础之前,我们首先来了解一下传统磁盘的劣势.我们知道一台PC机种都会包含CPU.内存.主板.硬盘.网卡等硬件,影响计算机性能的 组建包括:CPU.主板总线 ...

  2. java web学习总结&lpar;十四&rpar; -------------------JSP原理

    一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...

  3. 我的ORM之十二 -- 支持的数据库及差别

    我的ORM索引 支持最好的是SqlServer2005,Sqlserver2008,SqlServer2012 ,后续将支持:MySql,Sqlite,Oracle. 1.分页差别 MsSql 200 ...

  4. selenium-webdriver&lpar;python&rpar; &lpar;十四&rpar; -- webdriver原理

    之前看乙醇视频中提到,selenium 的ruby 实现有一个小后门,在代码中加上$DEBUG=1 ,再运行脚本的过程中,就可以看到客户端请求的信息与服务器端返回的数据:觉得这个功能很强大,可以帮助理 ...

  5. JavaWeb---总结&lpar;十四&rpar;JSP原理

    一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...

  6. javaweb学习总结&lpar;十四&rpar;——JSP原理

    一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...

  7. SSH深度历险(十) AOP原理及相关概念学习&plus;AspectJ注解方式配置spring AOP

    AOP(Aspect Oriented Programming),是面向切面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP之所以能得到广泛应用,主要是因为它将应用系统拆分分了2个部分 ...

  8. javaweb&lpar;十四&rpar;——JSP原理

    一.什么是JSP? JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术. JSP这门技术的最大的特点在于,写jsp就像在写h ...

  9. selenium-webdriver&lpar;python&rpar; &lpar;十四&rpar; -- webdriver原理(转)

    之前看乙醇视频中提到,selenium 的ruby 实现有一个小后门,在代码中加上$DEBUG=1 ,再运行脚本的过程中,就可以看到客户端请求的信息与服务器端返回的数据:觉得这个功能很强大,可以帮助理 ...

随机推荐

  1. 阿里云添加路由的Windows批处理文件

    一段很好的学习bat程序的示例代码,如下: @echo off route print -4 "10.0.0.0" | find "10.0.0.0" > ...

  2. 关于editor网页编辑器ueditor&period;config&period;js 配置图片上传

    最近公司项目在做一个门户网站,其中新闻和简介等部分使用到了ueditor编辑器,但是上级明确指示需要图片上传这个功能,这时却发现图片上传功能不能正常使用,上传时一直报错,网上收了好几个处理办法,都说的 ...

  3. 用c&num;开发微信 &lpar;10&rpar; JS-SDK 基本用法- 分享接口&OpenCurlyDoubleQuote;发送到朋友”

    微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包.通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用微信分享. ...

  4. C&num;基础--之数据类型

    C#基础--之数据类型 摘自:http://www.cnblogs.com/tonney/archive/2011/03/18/1987577.html 在第一章我们了解了C#的输入.输出语句后,我这 ...

  5. Mininet实验 OpenFlow1&period;3协议基于Mininet部署与验证

    参照:OpenFlow1.3协议基于Mininet部署与验证 安装过程,参考原文. 实验 使用ifconfig查看本机IP地址:192.168.1.101 进入OpenDayLight界面,cd到bi ...

  6. 免安装版Tomcat6&period;0启动方法

    免安装版Tomcat6.0启动方法 1.下载Tomcat Zip压缩包,解压. 2.修改startup.bat文件: 在第一行前面加入如下两行 SET JAVA_HOME=JDK目录 SET CATA ...

  7. apache反向代理 负载均衡

    开启模块: LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so LoadModule slotmem_sh ...

  8. BIEE Setup

    ORACLE 出品的产品绝对都可以称得上装X神器:安装文件一定要大(小水管不让你下个三天三夜那都不叫oracle),系统内存必须得大.硬盘空间必须足够多.安装时间必须足够长.各种配置必须足够复杂.学习 ...

  9. USB系列之八:透过ASPI执行SCSI命令

    在<USB系列之七>里我们介绍了ASPI的规范,并对一系列ASPI的命令做了测试,其中的02号命令是执行SCSI命令,我们专门在这篇文章中介绍,在<USB系列七>中,我们已经了 ...

  10. python新手 实践操作 作业

    #有如下值集合 [11,22,33,44,55,66,77,88,99],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中.即: {'k1': 大于66的所 ...