AppBoxFuture(八): 另类的ORM实现
通常的ORM实现基于配置或注释,由反射或Emit生成相应的Sql语句,然后将Sql发送给数据库解析Sql字符串生成AST再交给优化器处理后执行,返回的数据再经由反射或Emit转换为相应的实体实例。作者认为上述方式主要存在以下两个问题:
- 实体类代码是硬编码的,如果实体类定义变更必须重新编译应用再部署,不利于实现运行时动态变更实体定义;
- CRUD操作转换为Sql的实现复杂,且需要针对不同的数据库做适配优化。
由于作者追求极致简单的系统架构以及丝般顺滑的开发体验,所以作者采用了另类的方式在框架内实现了ORM,之于另类在什么地方我们先通过一些简单示例后再来说明一下实现原理。
一、CRUD操作
还是用系统自带的Emploee模型作为示例,在IDE新建服务模型添加以下代码保存发布后可通过主菜单->Service->Invoke运行测试:

//事务新建两条记录
var emp1 = new Entities.Emploee();
emp1.Name = "Rick";
emp1.Account = "rick@appbox.dev";
emp1.Birthday = new DateTime(1977, 3, 16);
var emp2 = new Entities.Emploee();
emp2.Name = "Johne";
emp2.Account = "johne@appbox.dev"
emp2.Birthday = new DateTime(1979, 1, 2);
var txn = await Transaction.BeginAsync();
try {
await EntityStore.SaveAsync(emp1, txn);
await EntityStore.SaveAsync(emp2, txn);
await txn.CommitAsync();
} catch (Exception ex) {
txn.Rollback();
}
//查询记录
var q = new TableScan<Entities.Emploee>();
q.Filter(t => t.Name == "Rick");
var emps = await q.ToListAsync();
//更新记录
emps[0].Name = "Rick Lu";
await EntityStore.SaveAsync(emps[0]);
//删除记录
await EntityStore.DeleteAsync(emps[0]);
以上只是已实现的一些Api示例,复杂的如根据索引查询、聚合查询等Api正在设计开发中。
二、实现原理
设计时:
这部分实现重度依赖Roslyn功能,服务端在开发人员登录至IDE后会通过Roslyn生成虚拟项目。

- 实体模型保存时服务端生成虚拟的实体类代码,并加入虚拟项目内;
- 服务模型保存时服务端生成虚拟的服务类代码,并加入虚拟项目内;发布时服务端的编译引擎解析虚拟的服务代码,然后转换为运行时服务代码,再通过Roslyn编译为动态服务组件。其中虚拟代码转换为运行时代码的过程主要是:
- 将实体属性取赋值操作(eg: entity.Name = "aa" 或 var temp = entity.Name)转换为针对运行时Entity类的GetXXX()及SetXXX()操作。这里需要注意的是运行时只存在一个Entity类(类似于KVO通过字典表保存属性值);
- 将查询条件转换为可序列化的表达式,这样存储引擎执行查询命令时可委托clr emit生成过滤指令,存储引擎在扫描时直接使用过滤指令计算满足条件的记录。
运行时:
这部分实现参考以下流程图,需要注意的是存储引擎是基于RocksDB的,实体数据转换为KV数据(如Key=Id, Value=[字段标识:字段值;字段标识:字段值]),这样转换过程就不需要使用反射或Emit。

三、性能测试
作者做了简单的性能测试(单节点I74C8G虚拟机):
- 并发插入不带索引不带外键的简单实体约28000tps;
- 通过惟一索引查询约80000qps;
- 带条件扫描少量记录约35000qps。
四、查询限制
- 存储引擎不支持join,可通过分别查询出数据后利用Linq做join操作;
- 存储引擎暂只支持根据Entity.Id或指定索引查询排序,不支持自定义排序。
五、本篇小结
本篇主要介绍了框架集成的ORM的另类实现,Github上的运行时已经更新可测试。如果您有问题或Bug报告,请留言或在Github提交Issue。
AppBoxFuture(八): 另类的ORM实现的更多相关文章
- Django框架(八) Django之ORM数据库操作
创建模型 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对一的关系( ...
- laravel5.5源码笔记(八、Eloquent ORM)
上一篇写到Eloquent ORM的基类Builder类,这次就来看一下这些方便的ORM方法是如何转换成sql语句运行的. 首先还是进入\vendor\laravel\framework\src\Il ...
- MySQL 第八篇:ORM框架SQLAlchemy
一 介绍 SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取 ...
- 第八篇:ORM框架SQLAlchemy 了解知识
一 介绍 SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取 ...
- AppBoxFuture: Sql存储的ORM查询示例
上篇介绍集成第三方Sql数据库时未实现如导航属性.子查询等功能,经过大半个月的努力作者初步实现了这些功能,基本上能满足80%-90%查询需求,特别复杂的查询可以用原生sql来处理,下面分别示例介绍 ...
- Bitter.Core系列八:Bitter ORM NETCORE ORM 全网最粗暴简单易用高性能的 NETCore 之 事务
Bitter.Core 编写事务相当简单,Bitter.Core 尽可能的将代码编写量降为最低,例外一方方面保证客户主观能控制代码.Bitter.Core 事务提交,支持Builkcopy事务,原生事 ...
- Python之旅:MySQL系列
第一篇:初识数据库 第二篇:库操作 第三篇:表操作 第四篇:数据操作 第五篇:索引原理与慢查询优化 第六篇:数据备份.pymysql模块 第七篇:视图.触发器.事务.存储过程.函数 第八篇:ORM框架 ...
- laravel框架总结(八) -- ORM模型
ORM模型简介 1>什么是ORM? ORM,即 Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样,我们在操作具体的 ...
- 我的第一个python web开发框架(32)——定制ORM(八)
写到这里,基本的ORM功能就完成了,不知大家有没有发现,这个ORM每个方法都是在with中执行的,也就是说每个方法都是一个完整的事务,当它执行完成以后也会将事务提交,那么如果我们想要进行一个复杂的事务 ...
随机推荐
- 《How Tomcat works》
容器是一个处理用户servlet请求并返回对象给web用户的模块. org.apache.catalina.Container接口定义了容器的形式,用四种容器:Engine(引擎),Host(主机), ...
- Git - Git简介与客户端安装
简介 Git是目前世界上最先进的分布式版本控制系统(没有之一)! 集中式版本控制系统(CVS/SVN),版本库是集中存放在中央服务器的,而一般工作的时候,用的都是自己的电脑,所以要先从中央服务器取得最 ...
- NetCore WebAPI开发探索
一.创建项目 新建api项目: 建好之后,一个默认的控制器已经有了: 运行就可以直接访问get接口获取数据: 二.跨平台部署 部署方面,微软已经完善的很好了,基本上算是傻瓜式操作.项目右键选择发布 ...
- 2018简约商务工作汇报工作总结公司培训团队介绍PPT模
这几款ppt模板都是简约大气类型的,32页足够丰富,有完整结构框架,可以修改文字图片直接套用模板,是通用的商务ppt模板. 模版来源:http://ppt.dede58.com/gongzuohuib ...
- UIView创建xib
这里有两种类都可以实现,但是推荐用Empty类来创建 (Empty): 参考链接:https://blog.csdn.net/wtdask/article/details/76439295 https ...
- 利用QQ获取ip
首先启动任务管理器,选择性能选型,点击打开资源管理器 点击网络,找到qq.exe 点击下面的TCP链接 最好让你的qq好友发一个离线文件,在接收的时候注意远程连接,即使您所要的你好友的ip地址
- Linux下使用 github+hexo 搭建个人博客06-next主题接入数据统计
之前说了 next 主题的优化和接入评论系统.让我们完成了自己所需的页面风格和排版,也可让访问用户在每篇博文评论,完成博主和访问用户的交互. 本章我们继续讲解其他重要功能. 既然是一个网站,那么我们就 ...
- ERROR: Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/Library/Python/2.7/site-packages/itsdangerous' Consider using the `--user` option or check the permissions
近期练习flask写个blog, 安装flask扩展时 pip install Flask-WTF 报ERROR: Could not install packages due to an Envir ...
- mysql-python 安装错误: Cannot open include file: 'config-win.h': No such file or directory
问题描述: pip instal MySQL-python 出现如下错误: Installing collected packages: MySql-python Running setup.py i ...
- 浅谈Django基础(HttpResponse、render、redirect)
1. 使用之前先导入他们 from django.shortcuts import HttpResponse, render, redirect 2. HttpResponse: 它是作用是内部传入一 ...