NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode。
整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含多年开发经验于其中,代表作有百亿级大数据实时计算项目。
开源地址:https://github.com/NewLifeX/X (求star, 754+)
扩展查询
前文《[NewLife.XCode]实体类详解》中有讲到扩展查询,XCode生成实体类代码时,在模型类有一个region叫“扩展查询”,一般是FindByAbc/FindAllByAbc的形式。
扩展查询以数据表索引为依据来生成:
- 唯一索引(含主键)生成FindByAbc方法(如FindByName),返回单个对象;
- 非唯一索引生成FindAllByAbc方法(如FindAllByClassID),返回对象列表(非null);
如上图,可知Entity实体基类内部,查询方法分为单对象查询的Find和对象列表的查询FindAll。
实际上,Find最终调用FindAll方法查一行。
Find/FindAll有多个重载,最主要的地方都是构造where查询条件。
下划线_是每个实体类都有的内嵌类,它包含了每一个字段的Field引用,借助运算符重载,可以很方便的构造查询条件,例如上面的_.Name == name最终会生成 where Name='Stone'
因为是内嵌类,在实体类内部使用的时候非常方便。但要是想要实体类外部使用,就麻烦很多了,需要带上实体类类名。
原则:XCode是充血模型,不管多么简单的查询,建议都封装Find/FindAll/Search等方法供外部使用。
高级表达式查询
仅靠一两个字段的简单查询,肯定无法满足各种业务要求,我们需要更强大的查询支持,特别是根据不同条件拼接不同语句。
上面是两个非常典型的业务查询。
这里请出了条件表达式WhereExpression,实际上它只有两个功能,&表示And,|表示Or,根据表达式级别支持括号运算。
exp&=xxx 是最常用的写法,右边一般是各种Field表达式。
上面第一个例子,生成的查询语句可能是 select * from Student where classid=?classid and name like '%?key%'
为什么说“可能”?因为classid为0,或者key为空时,并不会参与拼接查询语句。
第二个例子稍微复杂一些,首先对key进行精确查询,找到了就返回,若是没找到,则开启模糊查询。
这里遇到了等于、包含、区间等判断操作,后面会详解所有支持的操作。
如非必要,建议保留select * 的查询方式,而不是指定列。
码农法则:数据库压力小于100qps时不要考虑指明select列来优化,大多数系统活不到需要优化的明天!
高级分页
两个例子都出现了一个PageParameter参数page,这是分页参数,包含分页查询以及排序所需要的数据。
PageIndex和PageSize指定页序号和每页大小,这是内部建立分页查询的核心依据;
Sort 指定排序字段,Desc 指定是否降序(默认升序);
RetrieveTotalCount 指定是否或者总记录数,若为true,则在查询记录集之前,先查询满足条件的总行数TotalCount,用于分页PageCount。此时等于执行两次数据库查询;
RetrieveState 指定是否获取统计 State,若为true,则在查询记录集之后,执行聚合查询,对数字型字段使用Sum聚合。此时最多可能执行3次数据库查询;
XCode要求数据查询必须考虑分页,没有分页的系统一般死在100万行以内。
Field扩展
内嵌类_引用的字段是Field,它继承自FieldItem。
Field/FieldItem全部功能:
- Equal 等于,操作符==
- NotEqual 不等于,操作符!=
- 大于操作符>,大于等于>=
- 小于操作符<,小于等于<=
- StartsWith 字符串开始,like '{0}%'。(支持索引)
- EndsWith 字符串结束,like '%{0}'
- Contains 字符串包含,like '%{0}%'
- In 集合包含,支持列表集合、字符串子查询和SelectBuilder子查询,集合只有一个元素时转为相等操作
- NotIn 集合不包含,支持列表集合、字符串子查询和SelectBuilder子查询,集合只有一个元素时转为不相等操作
- IsNull 是否空
- NotIsNull 不是空
- IsNullOrEmpty 字符串空或零长度
- NotIsNullOrEmpty 字符串非空非零长度
- IsTrue 是否True或者False/Null,参数决定两组之一
- IsFalse 是否False或者True/Null,参数决定两组之一
- Between 时间区间,大于等于开始,小于结束,如果开始结束都只有日期而没有时分秒,则结束加一天,如(2019-04-17, 2019-04-17)查 time>='2019-04-17' and time<2019-04-18'
排序字句/分组聚合
- Asc,升序
- Desc,降序。order by name desc
- GroupBy,分组。group by name
- As,聚合别名
- Count,计数
- Sum,求和
- Min,最小
- Max,最大
查询的本质
查询的本质是五参数版FindAll(where, order, selects, start, maxnums),其它查询方式都由它转化而来!
Entity实体基类封装了各种常用的查询方法:
对于单表查询的XCode来说,五参数版FindAll很容易得到 select [selects] from [table] where [where] order by [order] limit [start], [maxnums] 语句,根据这个理念,FindAll可以支持任意复杂查询!
最终查询语句,由SelectBuilder类承载。
系列教程
NewLife.XCode教程系列[2019版]
- 增删改查入门。快速展现用法,代码配置连接字符串
- 数据模型文件。建立表格字段和索引,名字以及数据类型规范,推荐字段(时间,用户,IP)
- 实体类详解。数据类业务类,泛型基类,接口
- 功能设置。连接字符串,调试开关,SQL日志,慢日志,参数化,执行超时。代码与配置文件设置,连接字符串局部设置
- 反向工程。自动建立数据库数据表
- 数据初始化。InitData写入初始化数据
- 高级增删改。重载拦截,自增字段,Valid验证,实体模型(时间,用户,IP)
- 脏数据。如何产生,怎么利用
- 增量累加。高并发统计
- 事务处理。单表和多表,不同连接,多种写法
- 扩展属性。多表关联,Map映射
- 高级查询。复杂条件,分页,自定义扩展FieldItem,查总记录数,查汇总统计
- 数据层缓存。Sql缓存,更新机制
- 实体缓存。全表整理缓存,更新机制
- 对象缓存。字典缓存,适用用户等数据较多场景。
- 百亿级性能。字段精炼,索引完备,合理查询,充分利用缓存
- 实体工厂。元数据,通用处理程序
- 角色权限。Membership
- 导入导出。Xml,Json,二进制,网络或文件
- 分表分库。常见拆分逻辑
- 高级统计。聚合统计,分组统计
- 批量写入。批量插入,批量Upsert,异步保存
- 实体队列。写入级缓存,提升性能。
- 备份同步。备份数据,恢复数据,同步数据
- 数据服务。提供RPC接口服务,远程执行查询,例如SQLite网络版
- 大数据分析。ETL抽取,调度计算处理,结果持久化