ORMX的交互语法是为了跟前端交互时更灵活的让前端决定查询参数而设计的 关键字:ORM,NETCORE ORM,.NET,数据库管理
前端语法
针对动态变量比较多的情况,按照之前编码模式压力总是给到后端!:dizzy_face:为了保住头发,于是熬夜创造了一套前端语法。
ORMSearch
前端语法主要使用 SetCondition 来设定查询条件,并且属性方法只能使用 Equals
ORMXSearch<Model.User> search = new ORMXSearch<Model.User>();
search.SetCondition(m => m.Name.Equals("知时"));
// 以下方法无效
search.SetCondition(m => m.Name == "知时");
// 封装好的 ORMXSearch 实例可以直接传入 Where
table.Where(search).Find();
前端交互
前端语法的构造函数也可以接收一个 Dictionary<string, string>,这样更方便与前端的 JSON 进行交互
public IActionResult PostSearch(Dictionary<string, string> searchObj)
{
var search = new ORMSearch<Model.Company>(searchObj);
// .. 逻辑代码
return new DefaultActionResult { Code = "0000" };
}
前端语法是基于对象的查询语法,所以要查询的属性必须是对象包含的属性
前端JSON
{
"searchObj": {
"属性名": "组名[*操作符,值]",
}
}
利用 JSON 的值传递查询的必要约束,下面我们来了解下约束的组成公式 组名[*操作符,值,逻辑符]
操作符和值
在公式中必须存在项
| 操作符 | 简写 | 说明 |
|---|---|---|
| = | E | 等于 |
| != | !E | 不等于 |
| IS | 无 | 主要处理 NULL 值和 NOT NULL 值 |
| > | 无 | 大于 |
| < | 无 | 小于 |
| >= | E> | 大于等于 |
| <= | E< | 不于等于 |
| BETWEEN | BW | 在区间 含边界,值用 \| 分割 |
| NOT BETWEEN | !BW 或 NBW | 不在区间 不含边界 |
| LIKE | % | 包含 |
| !LIKE | !% | 不包含 |
| IN | 无 | 在集合,集合内容使用 \| 分割 |
| !IN | 无 | 不在集合 |
| ASC | 无 | 从小到大排序,单独存在 |
| DESC | 无 | 从大到小排序,单独存在 |
当使用GET传参时 `=` 符号会被自动编码,请使用简写
值只能使用字符串格式,哪怕是 **IN** 和 **!IN** 值也是使用 **|** 拼接的字符串
``` json
{
"searchObj": {
"city": "[in,WZ|TZ|HZ]",
"name": "[like,%测试%]",
"sex": "[is,not null]",
"loginCount": "[=,0]",
"createTime": "[>, 2022-2-7][desc]"
}
}
```
组名和逻辑或
默认逻辑符是 AND,而组可以实现 OR 逻辑
{
"searchKey": {
"name": "G1[like,%测试%][LIKE,%游戏%]G2[LIKE,%老大%]",
"loginCount": "[=,0]",
"createTime": "G2[>,2022-2-1]"
}
}
对等的 SQL 如下
WHERE LoginCount = 0 AND
(CompanyName LIKE '%测试%' OR CompanyName LIKE '%游戏%') AND
(CompanyName LIKE '%老大%' OR CreateTime > '2022-02-01 00:00:00')
根据字段名获取查询语法
如果有需要,我们还可以获取属性是否已经存在查询条件
string con = search.GetCondition(m => m.Name);
// 输出结果 G1[like,%测试%,OR][LIKE,%游戏%,OR]G2[LIKE,%老大%]
排序优先级
ASC 和 DESC 的优先级会受到运行顺序影响
searchObject.SetCondition(m => m.Price.Equals("[asc]"));
searchObject.SetCondition(m => m.CreateTime.Equals("[asc]"));
以上代码对应 MYSQL 语句
ORDER BY Price ASC , CreateTime ASC
高级扩展
运行语句 Command(不推荐)
var items = entity.Command("select * from ormx_user");
为了尽可能的安全 **Command** 方法设置了单次只能执行一句语句的限制,如果像以下 **SQL** 注入的例子
> SELECT * FROM users WHERE username = '' OR '1'='1'; --' AND password = 'input_password';
程序就会报错,并返回提示
不允许执行多条语句
直接运行语句由于开放性太高,会破坏程序设定的稳定性和安全性 **(比如低性能的全表查询、运行恶意的系统级命令)**
如果无法避免请一定要合理设计权限范围,包括但不限于 数据库账号的权限、应用内可访问运行语句的角色权限
回调函数 OnCommand
table.OnCommand((driver) =>
{
Logger.Debug("============> " + driver.CommandString);
})
.FindAll();
使用 OnCommand 可以获取当前数据库交互的两个信息
public interface IDriver
{
// 开始时间
public DateTime StartTime { get; }
// 执行语句
public string CommandString { get; }
}
**OnCommand** 可用于开发过程中的语句查看调试,也可以用于记录当前服务器的性能。比如本站的 [性能监测工具](/Tools/Performance)
安全设计
**ORMX** 设计了 **防注入** 功能,就算是自由度较高的前端语法也是可以放心使用。并且过程并不需要对执行语句的拆解分析,所以并不会产生性能损耗 :sunglasses:
## 补充说明
如果项目的数据结构复杂并且会使用到一些高级特性,我更推荐您使用 [Entity Framework Core](https://learn.microsoft.com/zh-cn/ef/core/),它是微软官方支持的 ORM,与.NET Core 集成较好,适合大多数常规应用。
除此之外 SqlSugar 也是一种不错的选择。
但如果你对项目编译后的体积有严格的控制,那 ORMX 无疑是最好的选择。