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. Cinemachine简介

      先贴一下官方的Cinemachine文档Cinemachine Documentation 简介 使用   我们第一次使用Cinemachine时大概是这样一个流程: 在需要被控制的Camera上 ...

  2. 负载均衡框架 ribbon 一

    Ribbon开源地址:https://github.com/Netflix/ribbon/wiki/Getting-Started 1.Ribbon简介 负载均衡框架,支持可插拔式的负载均衡规则 支持 ...

  3. JavaScript的类数组

    类数组对象啊,被人问到它跟真正的数组对象有什么差别啊?说不上来就老埋汰了,只知道函数的arguments对象是个类数组对象,也有length属性,其他呢?干货奉上: 首先先说说数组吧: 1,当有新的元 ...

  4. CentOS系统python默认版本由python2改为python3

    一.了解 CentOS中如果安装有yum,一般会有python2的某个版本.命令行键入python,出现的python2的环境: [root@instance-hrnebyqu src]# pytho ...

  5. AspNetCore3.1_Secutiry源码解析_1_目录

    文章目录 AspNetCore3.1_Secutiry源码解析_1_目录 AspNetCore3.1_Secutiry源码解析_2_Authentication_核心项目 AspNetCore3.1_ ...

  6. SpringBoot入门系列(七)Spring Boot整合Redis缓存

    前面介绍了Spring Boot 中的整合Mybatis并实现增删改查,.不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/category/ ...

  7. 组件/ 外层数据初始化时候,不应该触发 on-change 事件

    组件/ 外层数据初始化时候,不应该触发 on-change 事件 watch: { value (value) { this.noOnChange = true // 外层传值 不触发on-chang ...

  8. SQL Prompt9 注册教程

    在网上找了很多,都是9.0一下的版本,所以这边来发个9.0的版本 然后下载的安装文件应该包括 这两个: 第一个是注册机,第二个是安装包,安装这里就不用讲了,下一步下一步就完事,安装完成之后,一定要断网 ...

  9. [Alg] 文本匹配-多模匹配-AC自动机

    1. 简介 AC自动机是一种多模匹配的文本匹配算法. 如果采用naive的方法,即依次比较文本串s中是否包含模式串p1, p2,...非常耗时.考虑到这些模式串中可能具有相同子串,可以利用已经比较过的 ...

  10. BeanShell断言:根据响应的2个数据的比较结果来决定断言

    需求:目前有一个请求,请求的响应中有2个值,aaa和bbb,我们比较aaa和bbb,如果aaa大于bbb,则断言通过,否则失败. 1.添加一个Dummy Sampler,模拟请求. 2.添加2个正则表 ...