EF 为代表的基于 LinqORM 框架总是 很重

他们的功能早已超出了一个 ORM 的范畴,

ORM 是 Object Relational Mapping ,从名字上看,其初衷是将 数据库中的字段 与 实体中的属性 进行关联映射,

但是 重型 ORM 框架 做了很多 额外 的事情 :

  • 数据库连接
  • 数据库事务包装
  • 实体缓存
  • 实体关联管理
  • 数据库表同步
  • 这些功能很好,
  • 强大的功能往往是死板的,

我们无法编写那些灵活的 Sql 去实现某些简便的操作。


以 MyBatis.NET、Dapper 为代表的,

则是基于开发者自行编写 Sql 的 ORM 框架又 太轻。

因为是自行编写 Sql ,

所以他们非常灵活,

但是用起来很 痛苦

哪怕是一个简单的 Insert ,Update 也得写 Sql,

而且还无法摆脱 数据库 兼容的问题。

你所编写的那些 Sql 在大部分情况下,只能用于一种 数据库


今天要向大家介绍一个 轻量级、不用写 Sql、可以兼容多数据库ORM 框架

Reface.NPI


什么是 NPI

NPI 全名 .Net Persistent Interface

这是一个利用 interface 实现的轻量级 ORM 框架,

它与市面上大多数的 ORM 框架不同,它不基于 Linq 进行数据库操作,而是基于 Method Name

例如

IList<User> SelectById(int id);

IList<User> SelecyByNameLike(string name);

void UpdatePasswordById(int id, string password);

bool DeleteById(int id);

NPI 提供了将上述 MethodName实际运算时的入参 生成 Sql执行信息 的方法。

此库不实现以下功能

  • 通过 AOP 产生 interfaceProxy ( 这个功能会在 Reface.AppStarter.NPI 中基于 Castle.DynamicProxy 实现 )
  • Sql执行信息 的执行
  • 将查询结果映射到对应的实体中 ( 这个功能会在 Reface.AppStarter.NPI 以基于 Dapper 实现 )
  • 对事务的管理 ( 这个功能预计在一个由 Reface.AppStarter 构建的一个业务框架中实现 )

不建议直接将此库用于业务功能的开发,

建议对该库进行一定的二次开发或封装后再投入使用,

开发者可以根据系统当前已经依赖的库进行封装。

计划在未来转为 .NetStandard 版本,以同时提供给 .NetCore 使用。

依赖项

  • Reface.StateMachine ( 库中对方法名称解析的过程依赖于此库 )
  • Reface ( 提供了一些基础的功能和方法,使用 .NetStandard2.0 编写 )

由于使用了 .NetStrand2.0,因此本库需要 .Net framework 4.6.1 及以上版本才能使用。

使用方法

四个分析器

系统中针对四种数据库不同的操作(增删改查),分别提供了四个不同的语义分析器

  • ISelectParser
  • IInsertParser
  • IUpdateParser
  • IDeleteParser

这四种转化器能够将一个字符串分析成为结构化的数据库处理结构,如

ISelectParser parser = new DefaultSelectParser();
string command = "ByIdAndName";
SelectInfo info = parser.Parse(command);
// info.Fields = [];
// info.Conditions[0].Field = "Id";
// info.Conditions[1].Field = "Name";
// info.Orders = [];

四种分析器分别能生成四种不同的语句结构:

Parser 结果的类型
ISelectParser SelectInfo
IInsertParser InsertInfo
IUpdateParser UpdateInfo
IDeleteParser DeleteInfo

这些 xxxInfo 的结构并不复杂,这里将不对其展开进行更多的介绍。

四个分析器的整合

ICommandParser 对四个分析器做了整合,以便我们不关心对方法的区分而直接得到 ICommandInfo

SelectInfo , InsertInfo , UpdateIfoDeleteInfo 都实现了 ICommandInfo 接口。

ICommandParser 通过方法的第一个单词对方法名进行分类,哪些前缀属于查询、哪些前缀属于更新,都是由它的实现的。

库中的 DefaultCommandParser 按照下面的 首单词 进行逻辑区分 :

查询语句

  • Get
  • Select
  • Fetch
  • Find
  • PagingGet
  • PagingSelect
  • PagingFetch
  • PagingFind

新增语句

  • Insert
  • New
  • Create

更新语句

  • Update
  • Modify

删除语句

  • Delete
  • Remove

下面的例子是分析了一个更新语句。

ICommandInfo 中的 Type 字段有助于你判断应当将 ICommandInfo 转化为一个具体的 Info

string command = "UpdateNameById";
ICommandParser parser = new DefaultCommandParser();
ICommandInfo info = parser.Parse(command);
if (info.Type == CommandInfos.Update)
UpdateInfo updateInfo = (UpdateInfo)info;
// updateInfo.SetFields[0].Field = "Name";
// updateInfo.Conditions[0].Field = "Id";

通过方名和参数生成执行信息

执行信息包含两个信息

  • Sql 语句
  • Sql 参数

在库中,生成执行信息是由 ISqlCommandGenerator 完成的。

// ISqlCommandGenerator.cs
using System.Reflection; namespace Reface.NPI.Generators
{
public interface ISqlCommandGenerator
{
SqlCommandDescription Generate(MethodInfo methodInfo, object[] arguments);
}
}

设计该接口的初衷是希望使用方是以 AOP 的方式拦截某个方法的执行,

并将 MethodInfo拦截到的入参 传递给 ISqlCommandGenerator

再根据生成的执行信息直接执行,得到结果。

目前库中有一个它的实现类型 : DefaultSqlServerCommandGenerator

你会从名字上发现,它是面向 SqlServer 的实现,

很明显,不同的 数据库 往往支持的语句并不相同。

因此,为不同的 数据库 编写不同的 ISqlCommandGenerator 是有必要的。

SqlCommandDescripion 是一个简单的数据结构,它包含 SqlCommandParameters 两个主要的属性,使用这两个属性可以完成后续的 Sql 执行。

注意事项

  • 对于表名的获取,是基于 INpiDao<TEntity> 中的 TEntity 来完成的,

    通过反射 TEntity 上的 System.ComponentModel.DataAnnotations.Schema.TableAttibute 特征来获取表名。
  • 由于 TableAttribute 在很多常见库中出现,所以要注意不要引用错了。
  • Reface.NPI 允许你重写对表名的获取,对字段的获取等逻辑,重写方法会在后面的文章中介绍。

方法名及预期 Sql 参照表

方法名称 期望的 Sql 说明
SelectById select * from [table] where id = ? 以 Id 作为条件查询实体
SelectNameAndAgeById select name, age from [table] where id = ? 以 Id 作为条件,只查询 Name 和 Age 字段
SelectByRegistertimeGreaterthan select * from [table] where Registertime > ? 查询 RegisterTime 大于参数的实体
SelectByRegistertimeGteq select * from [table] where Registertime >= ? 查询 RegisterTime 大于等于参数的实体
SelectByIdAndName select * from [table] where id = ? and name = ? 按 Id 且 Name 作为条件查询实体
SelectByIdOrName select * from [table] where id = ? or name = ? 以 Id 或 Name 作为条件查询实体
SelectByIdOrNameLike select * from [table] where id = ? or name like ? 以 Id 或 Name Like 作为条件查询实体
SelectByIdOrderbyName select * from [table] where id = ? order by name 以 Id 查询并以 Name 排序
SelectByIdOrderByNameDesc select * from [table] where id = ? order by name desc 以 Id 作为条件并以 Name 倒序排序
DeleteById delete from [table] where id = ? 以 Id 作为条件删除
UpdatePasswordById update [table] set password = ? where id = ? 以 Id 作为条件更新 Password
UpdatePasswordByNameLike update [table] set password = ? where name like ? 以 Name Like 作为条件更新 Password
UpdateStateAndTokenByLastoprtimeGt update [table] set state=?,token=? where lastoprtime > ? 以 LastOprTime 大于 作为条件更新 state 和 token
UpdateById update [table] set ... where id = ? 以 Id 作为条件,并以 Id 以外的字段作为 Set 子句
UpdateWithoutCreatetimeById update [table] set ... where id = ? 以 Id 作为条件,并以 Id 和 Createtime 以外的字段作为 Set 子句
UpdateWithoutStateCreatetimeById update [table] set ... where id = ? 以 Id 作为条件,并以 Id 、State 和 Createtime 以外的字段作为 Set 子句
InsertWithoutIdCreatetime(Entity) insert into [table] (...) values(?,...,?) 排除 Id 和 Createtime 字段新增实现

相关链接

下期预告 : 《NPI 方法规则详解》

将详细地说明四种操作所支持的各种操作。

EF 太重,MyBatis 太轻,ORM 框架到底怎么选 ?的更多相关文章

  1. Abp太重了?轻量化Abp框架

    本文首发于个人博客(https://blog.zhangchi.fun/) 在进行框架的选型时,经常会听到"***框架太重了"之类的声音,比如"Abp太重了,不适合我们. ...

  2. EF、Dapper、NHibernate等ORM框架的比较及优缺点

    什么是ORM? ORM的全称是Object Relational Mapping,即对象关系映射.它的实现思想就是将关系数据库中表的数据映射成为对象,以对象的形式展现,这样开发人员就可以把对数据库的操 ...

  3. mybatis(一)常见ORM框架及JDBC操作工具类

      转载:https://www.cnblogs.com/wuzhenzhao/p/11075569.html 在Java 程序里面去连接数据库,最原始的办法是使用JDBC 的API.我们先来回顾一下 ...

  4. 【EF 4】ORM框架及其流行产品之一EF介绍

    导读:跳进了多租户切换数据库的坑,那么就继续走下去吧.在我们的项目中,是运用EF实现对数据库的操作,那么EF其实是.NET系统中,基于ORM框架的一个产品实现.在java那边,则有Hibernate和 ...

  5. ORM框架之EntityFramework介绍

    ORM框架之EntityFramework介绍 1. 简介 大家好!我是高堂. 作为一位伪前端程序猿,我给大家介绍一下微软的自家的 ORM框架. ADO.NET Entity Framework 以下 ...

  6. 轻量级ORM框架初探-Dapper与PetaPoco的基本使用

    一.EntityFramework EF是传统的ORM框架,也是一个比较重量级的ORM框架.这里仍然使用EF的原因在于为了突出轻量级ORM框架的性能,所谓有对比才有更优的选择. 1.1 准备一张数据库 ...

  7. orm框架与缓存的关系

    1.mybatis规定,一级缓存没必要bean类实现序列化,但二级缓存bean类必须实现序列化. 因为二级缓存是基于namespace的也就是基于接口的,二级缓存可以设置存储源,可以是redis或者m ...

  8. ORM框架EF

    应用程序和数据库采用Tcp协议通讯 ORM框架有: NHibernate ,Dapper ,Mybatis 底层是 ADO.Net 好处: 1.面向对象 2.没有sql减少学习成本,快速开发 3.编译 ...

  9. 轻量型ORM框架Dapper的使用

    在真实的项目开发中,可能有些人比较喜欢写SQL语句,但是对于EF这种ORM框架比较排斥,那么轻量型的Dapper就是一个不错的选择,即让你写sql语句了,有进行了关系对象映射.其实对于EF吧,我说下我 ...

随机推荐

  1. LVM简介及CentOS7 LVM操作实战

    LVM简介LVM是逻辑盘卷管理(LogicalVolumeManager)的简称,它是Linux环境下对磁盘分区进行管理的一种机制,LVM是建立在硬盘和 分区之上的一个逻辑层,来提高磁盘分区管理的灵活 ...

  2. mui中如何使用tab来切换子页面 mui-bar, mui-bar-tab

    mui是前端框架但是很多人用它写移动端 那么mui底部切换是怎么做到的呢? 如何点击某个tab来切换不同的页面? 解答: 1首先我们需要引入mui框架的底部tab元素 代码如下 <!--tabl ...

  3. UICollectionViewCell设置阴影

    //@mg:masksToBounds必须为NO否者阴影没有效果 // cell.layer.masksToBounds = NO; cell.layer.contentsScale = [UIScr ...

  4. 「从零单排HBase 05」核心特性region split

    HBase拥有出色的扩展性,其中最依赖的就是region的自动split机制. 1.split触发时机与策略 前面我们已经知道了,数据写入过程中,需要先写memstore,然后memstore满了以后 ...

  5. 开篇词The Start以及[Vjudge][HDU2242]空调教室

    开篇 这是我写的第一篇记录好题的博客,也是博客园上我发布的第一篇博客. 以后我的所有博客都将在洛谷和博客园上同时发布,同志们有兴趣的在哪里都可以看一看. [https://www.luogu.com. ...

  6. 使用 ALSAlib 播放 wav

    在 ARM 2440 开发板上正常播放 16bit  44100 采样率的wav , 为了程序简单,没有判断返回值. 补充,在 ubunto 上也能正常播放. 编译方法: arm-linux-gcc ...

  7. C++ 文件操作 FILE*

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> //编程题:往文件里写入字母表的26个字母. //要求:如果字母对应编码值 是奇数则写 ...

  8. async,await怎么用

    async声明一个函数是异步的,await用于等待异步完成,并且await只能在async中使用. 使用async,await并行处理请求,速度减半: 将多个promise直接发起请求,先执行asyn ...

  9. 五分钟完成 ABP vNext 通讯录 App 开发

    五分钟完成 ABP vNext 通讯录 App 开发 ABP vNext(后文简称Abp)是 Volo 公司堪称艺术品级的应用开发框架,它基于领域驱动设计(DDD)的思维,创新地采用了模块化的设计.A ...

  10. apply 和 call 方法详解【转载】

    本文转载至:http://blog.csdn.net/business122/article/details/8000676 我在一开始看到javascript的函数apply和call时,非常的模糊 ...