# NoORM
**Repository Path**: zhang_xiangm/no-orm
## Basic Information
- **Project Name**: NoORM
- **Description**: 厌倦了铺天盖地的ORM框架,从数据库查询出数据,然后组装成html,真的是非常简单的事情。NoORM提供前端到数据库的直通车。部署一个服务即可通过restfull风格的API查询数据,是前端工程师的福音。
- **Primary Language**: C#
- **License**: GPL-3.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 1
- **Created**: 2021-07-24
- **Last Updated**: 2024-07-26
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# NoORM
### 介绍
从数据库查询出数据,然后组装成html,如此简单的事情,为什么要那么多的约定和配置,为什么要造那么多轮子。数据库里存放的二维表格,到web服务器经过多次转换变成了对象集合,到api层变成json,到浏览器再变成html,这就是热衷于ORM技术的架构师干的糊涂事。如果你厌倦了这种翻手为云,覆手为雨的套路,请静下心来思考编程的真正目的是什么。NoORM提供前端到数据库的直通车。部署一个服务即可通过restful风格的API查询数据,是前后端分离型项目的福音。NoORM的宗旨是使查询数据变得简单,并未提供数据安全方面的机制,如果您的项目对安全性有苛刻的要求,请下载源代码,在合适的位置注入您的安全插件,这对熟悉.net5的工程师来说,并不是什么难事。
### 开发环境
- Visual Studio 2019
- c#
- .net 5
### 平台兼容性
- windows
- linux
- macos
### 数据库兼容性
- mysql
- sqlserver
- oracle
- posgresql
- sqlite
### 数据库连接字符串
- 配置文件:appsettings.json
- 配置项:
```
"ConnectionStringConfigs": {
"test": //数据库配置名称,未必是真实的数据库名
{
"ConnectionString": "server=.;database=test;uid=sa;pwd=123456;", //ado.net标准数据库连接字符串,具体参考各数据库驱动程序集的相关说明
"ConnectionClassName": "System.Data.SqlClient.SqlConnection" //IDbConnection接口的实现类的类全名,具体参考各数据库驱动程序集的相关说明
},
...
}
```
### url占位符说明
| 占位符名称 |
说明 |
| {数据库名} |
数据库配置名称,忽略大小写 |
| {表名} |
要操作的数据表名,大小写是否敏感取决于具体的数据库产品及其配置 |
### 服务端变量说明
| 变量名称 |
变量说明 |
| $GUID |
服务端会将其替换成一个guid值,常常在inser时使用该变量来生成主键 |
| $NOW |
服务端会将其替换成服务器的当前时间 |
| $TICKS |
服务端会将其替换成服务器的当前时间的长整型时间戳,注意该时间戳在高并发场景中并不具备唯一性 |
### 请求字段说明
| 字段名称 |
数据类型 |
字段说明 |
| fields |
array<string> |
查询字段,如果为null,服务端默认为* |
| data |
object |
要新增或修改的数据,key为字段名称,value为字段值 |
| orderBy |
string |
排序字段 |
| pageSize |
int |
分页大小 |
| pageIndex |
int |
第几页,从0开始 |
| queries |
array<object> |
查询表达式 |
| --field |
string |
查询字段 |
| --operator |
string |
只能是如下值之一:< , <=,==,>= , <> , like,in,not in |
| --value |
object |
查询值 |
| --prefix |
string |
连接词,可选值:and , or |
| --leftBrackets |
string |
表达式左边的括号,可以是多个,如:( |
| --rightBrackets |
string |
表达式左右边的括号,可以是多个,如:) |
| groupFields |
array<string> |
分组字段,用于统计查询 |
| functions |
array<object> |
统计函数 |
| --functionName |
string |
函数名称 |
| --field |
string |
函数包裹的字段 |
| --resultName |
string |
给函数表达式取一个名字 |
### 响应字段说明
| 字段名称 |
数据类型 |
字段说明 |
| success |
boolean |
操作结果 |
| message |
string |
错误信息 |
| rowCount |
int |
分页查询时,表示在未分页前,满足查询条件的数据总行数 |
| data |
object |
当对数据库进行insert、update、delete操作时,其值为受影响的数据行数;
当对数据库进行read操作时,其值为一个json键值对;
当对数据库进行select、group、page时,其值为数组,数组的每个元素表示一行数据。
|
| serverReceiveTime |
string |
服务器接收到请求的时间 |
| serverSendTime |
string |
服务器开始向客户端发送数据的时间 |
### 添加数据
- url:/{数据库名}/{表名}.create
- method:post
- contentType:application/json
- body:
```
{
data:{
"Field1":"$GUID", //服务端变量,服务端会用Guid.NewGuid().ToString()替换,常用于生成主键
"Field2":123, //数值字段的值不加引号
"Field3":true, //布尔字段的值不加引号
"Field4":"字符串", //字符串字段值加引号
"Field5":"2021-01-01 13:01:01", //时间字段的值加引号,格式:yyyy-MM-dd HH:mm:ss
"Field6":"$NOW", //服务端变量,服务端会用DataTime.Now替换
...
}
}
```
- response:
```
{
"success": true, //操作结果
"message": null, //错误消息
"serverReceiveTime": "2021-04-21 08:39:57", //服务器接收到请求的时间
"serverSendTime": "2021-04-21 08:39:57", //服务器开始向客户端发送数据的时间
"data": 1 //新增的数据行
}
```
### 删除数据
- url:/{数据库名}/{表名}.delete
- method:delete
- contentType:application/json
- body:
```
{
queries:[
{
field:"字段名",
value:"字段值"
},{
prefix:"and", //连接词
field:"字段称",
operator:">", //操作符号,默认为=
value:1 //数值型值不加引号
},{
prefix:"and",
field:"字段称",
operator:"in",
value:[1,2,3] //in查询的value是一个数组
}
...
]
}
```
- response:
```
{
"success": true,
"message": null,
"serverReceiveTime": "2021-04-21 08:39:57",
"serverSendTime": "2021-04-21 08:39:57",
"data": 1 //删除的行数
}
```
### 修改数据
- url:/{数据库名}/{表名}.update
- method:post
- contentType:application/json
- body:
```
{
//更新的字段及其值
data:{
"Field1":"$GUID", //服务端变量,服务端会用Guid.NewGuid().ToString()替换,常用于生成主键
"Field2":123, //数值字段的值不加引号
"Field3":true, //布尔字段的值不加引号
"Field4":"字符串", //字符串字段值加引号
"Field5":"2021-01-01 13:01:01", //时间字段的值加引号,格式:yyyy-MM-dd HH:mm:ss
"Field6":"$NOW", //服务端变量,服务端会用DataTime.Now替换
...
},
//where条件
queries:[
{
field:"字段名",
value:"字段值"
},{
prefix:"and", //连接词
field:"字段称",
operator:">", //操作符号,默认为=
value:1 //数值型值不加引号
},{
prefix:"and",
field:"字段称",
operator:"in",
value:[1,2,3] //in查询的value是一个数组
}
...
]
}
```
- response:
```
{
"success": true,
"message": null,
"serverReceiveTime": "2021-04-21 08:39:57",
"serverSendTime": "2021-04-21 08:39:57",
"data": 1
}
```
### 查询一条数据
- url:/{数据库名}/{表名}.read
- method:post
- contentType:application/json
- body
```
{
//要查询的字段
fields:["字段1","字段2", ... ],
//where条件
queries:[
{
field:"字段名",
value:"字段值"
},{
prefix:"and", //连接词
field:"字段称",
operator:">", //操作符号,默认为=
value:1 //数值型值不加引号
},{
prefix:"and",
field:"字段称",
operator:"in",
value:[1,2,3] //in查询的value是一个数组
}
...
]
}
```
- response:
```
{
"success": true,
"message": null,
"serverReceiveTime": "2021-04-21 08:39:57",
"serverSendTime": "2021-04-21 08:39:57",
"data": {
Field1:"",
Field2:"",
...
}
}
```
### 查询多条数据
- url:/{数据库名}/{表名}.select
- method:post
- contentType:application/json
- body:
```
{
//要查询的字段
fields:["字段1","字段2", ... ],
//where条件
queries:[
{
field:"字段名",
value:"字段值"
},{
prefix:"and", //连接词
field:"字段称",
operator:">", //操作符号,默认为=
value:1 //数值型值不加引号
},{
prefix:"and",
field:"字段称",
operator:"in",
value:[1,2,3] //in查询的value是一个数组
},
...
]
}
```
- response:
```
{
"success": true,
"message": null,
"serverReceiveTime": "2021-04-21 08:39:57",
"serverSendTime": "2021-04-21 08:39:57",
"data": [
{
Field1:"",
Field2:"",
...
},
...
]
}
```
### 分页查询
- url:/{数据库名}/{表名}.page
- method:post
- contentType:application/json
- body:
```
{
orderBy:"排序字段",
pageSize:"10",
pageIndex:"0",
//查询表达式
queries:[
{
field:"字段名",
value:"字段值"
},{
prefix:"and", //连接词
field:"字段称",
operator:">", //操作符号,默认为=
value:1 //数值型值不加引号
},{
prefix:"and",
field:"字段称",
operator:"in",
value:[1,2,3] //in查询的value是一个数组
},
...
]
}
```
- response:
```
{
"success": true,
"message": null,
"serverReceiveTime": "2021-04-21 08:39:57",
"serverSendTime": "2021-04-21 08:39:57",
"rowCount":10000,
"data": [
{
Field1:"",
Field2:"",
...
},
...
]
}
```
### 分组统计
- url:/{数据库名}/{表名}.group
- method:post
- contentType:application/json
- body:
```
{
//分组字段
groupFields:["分组字段名1","分组字段名2",...],
//统计字段
functions:[{
functionName:"函数名称",
field:"字段名称",
resultName:"计算后的字段名"
},
...
],
//where条件
queries:[
{
field:"字段名",
value:"字段值"
},{
prefix:"and", //连接词
field:"字段称",
operator:">", //操作符号,默认为=
value:1 //数值型值不加引号
},{
prefix:"and",
field:"字段称",
operator:"in",
value:[1,2,3] //in查询的value是一个数组
},
...
]
}
```
- response:
```
{
"success": true,
"message": null,
"serverReceiveTime": "2021-04-21 08:39:57",
"serverSendTime": "2021-04-21 08:39:57",
"data": [
{
GroupField1:"",
GroupField2:"",
...
FunctionField1:"",
FunctionField2:"",
...
},
...
]
}
```
### 事务提交
url:/{数据库名}.transaction
method:post
contentType:application/json
body:
```
[
{
table:"表名",
operator:"insert", //可选值:insert,delete,update
data:{
"Field1":"$GUID", //服务端变量,服务端会用Guid.NewGuid().ToString()替换,常用于生成主键
"Field2":123, //数值字段的值不加引号
"Field3":true, //布尔字段的值不加引号
"Field4":"字符串", //字符串字段值加引号
"Field5":"2021-01-01 13:01:01", //时间字段的值加引号,格式:yyyy-MM-dd HH:mm:ss
"Field6":"$NOW", //服务端变量,服务端会用DataTime.Now替换
...
}
},{
table:"表名",
operator:"delete",
queries:[
{
field:"字段名",
value:"字段值"
},{
prefix:"and", //连接词
field:"字段称",
operator:">", //操作符号,默认为=
value:1 //数值型值不加引号
},{
prefix:"and",
field:"字段称",
operator:"in",
value:[1,2,3] //in查询的value是一个数组
},
...
]
},{
table:"表名",
operator:"update",
//要修改的数据
data:{
"Field1":"$GUID", //服务端变量,服务端会用Guid.NewGuid().ToString()替换,常用于生成主键
"Field2":123, //数值字段的值不加引号
"Field3":true, //布尔字段的值不加引号
"Field4":"字符串", //字符串字段值加引号
"Field5":"2021-01-01 13:01:01", //时间字段的值加引号,格式:yyyy-MM-dd HH:mm:ss
"Field6":"$NOW", //服务端变量,服务端会用DataTime.Now替换
...
},
//where条件
queries:[
{
field:"字段名",
value:"字段值"
},{
prefix:"and", //连接词
field:"字段称",
operator:">", //操作符号,默认为=
value:1 //数值型值不加引号
},{
prefix:"and",
field:"字段称",
operator:"in",
value:[1,2,3] //in查询的value是一个数组
},
...
]
},
...
]
```
- response:
```
{
"success": true,
"message": null,
"serverReceiveTime": "2021-04-21 08:39:57",
"serverSendTime": "2021-04-21 08:39:57",
"data": true
}
```