EFCore多数据库合并查询分页
EFCore多数据库合并查询分页
参照:二个表的数据 如何做分页?_两个表排序分页_深圳市热心市民市民的博客-CSDN博客
基本情况介绍:由于系统迭代,部分收藏表在老系统的数据库,部分在新api接口的数据库,现在有一个需求是在个人中心展示用户收藏的数据,按照收藏时间倒序排列,因为在APP端实际上就算瀑布流分页。
主体思路:通过将两个表通过条件筛选形成IQuerable,再通过Union联结,做的分页,再通过ToList()加载到内存里
query1.Union(query2).Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList();
但是经过尝试后,报错:Cannot use multiple DbContext instances within a single query execution。在一个查询里只能使用一个数据库上下文实例。因为来自两个不同的数据库所以query1和query2我们使用了两个不同的 DBContext
,配置了不同的数据库连接。结果就出现了上述的报错。转念又想有没有可能在一个负责管理实体对象的上下文中设置多个数据库那不就可以了吗?但是查阅资料,发现并不能实现。因为当存在多个数据库在 DbContext
里的 DbSet
没办法指定它属于哪个数据库。简而言之,就是一个 DBContext
只能对应一个数据库。
所以思路调整为从两个 DBContext
里查找出结果集(ToList()
加载到内存里),再将结果集合并后再做分页,这就涉及到怎么取数据能得到准确的结果还能使得查询效率最大化?假设我们是按照创建时间逆序,每页10条:
这里有一个容易犯错的思路:假设是第一页,先从A表里取10里取5条,再从B表里取5条,合并后再按照时间排序输出。这样做最大的问题是,没办法保证数据的准确性。因为极端一点可能最新的10条数据都来自B表,这样取是没办法保证数据准确性的。
以上错误的做法也给了我们参考意义,那各取多少条就能保证数据是准确的呢?答案是 pageNumber*pageSize
为什么呢?以第一页为例,假设每页10条,我从A表里取10条,再从B表里取10条,从合并后的20条里找出最新的10条,这是肯定合理的,它能涵盖这页数据全部来自其中一张表的情况。以此类推,第二页:各取20条;第三页:各取30条...以此类推。很容易发现问题,就是约到后面的页码,我们要取得数据越多。基本上是线性增加的,那就意味着到了后面的页码会出现我们之前不愿见到的局面:我们把大量的结果集都加载到了内存里,再进行合并排序分页。
参照的文章给了我们思路。因为我们分页基本上是在排序后进行的,所以我们每次分页的最后一条数据,可以作为下一页数据的的筛选判断条件。以我们文中例子,第一页第10条数据的创建时间一定是大于第二页的数据的。我们就可以在调用接口时除了我们的页码参数,把前一页码数据最后一条的创建时间也带上当作参数传入。结果是
var result1 = dbContext1.Colections.where(s=>s.CreateTime< timeParm).OrderByDescending(s=>s.CreateTime).Take(pageSize).ToList();
var result2 =dbContext2.Colections.where(s=>s.CreateTime< timeParm).OrderByDescending(s=>s.CreateTime).Take(pageSize).ToList();
仅仅只需要每次各从结果集取出pageSize条,甚至不需要pageNum的参数就能实现我们需要的效果。另外它还有个隐藏性能福利:我们通过where的筛选实现了 Skip((pageNumber - 1) * pageSize)
的效果,性能会更高。每次取出加载到内存的结果集都很小,实现了我们预期的效果。
EFCore多数据库合并查询分页的更多相关文章
- oracle 基础SQL语句 多表查询 子查询 分页查询 合并查询 分组查询 group by having order by
select语句学习 . 创建表 create table user(user varchar2(20), id int); . 查看执行某条命令花费的时间 set timing on: . 查看表的 ...
- .NET平台开源项目速览(7)关于NoSQL数据库LiteDB的分页查询解决过程
在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑) 与 .NET平台开源项目速览(3)小巧轻量级NoSQL文件数据库LiteDB中,介绍了LiteDB的基本使用情况以及部 ...
- 基于Mysql数据库的SSM分页查询
前言: Hello,本Y又来了,"分页"在我们使用软件的过程中是一个很常见的场景,比如博客园对于每个博主的博客都进行了分页展示.可以简单清晰的展示数据,防止一下子将过多的数据展现给 ...
- mysql表查询、多表查询(增强查询的使用)子查询、合并查询,外连接,mysql5种约束,自增长
一.查询加强 1.在mysql中,日期类型可以直接比较,需要注意格式 2.%:表示0到多个字符, _:表示单个字符 exp:显示第二个字符为大写O的所有员工的姓名和工资 select name fr ...
- TODO:数据库优化之分页
TODO:数据库优化之分页 本文的例子是以MongoDB数据库为准,其它数据库各位也可以举一反三进行优化. 在MongoDB中分页使用 a.skip(n)跳过前n个匹配的文档: b.limit(m)返 ...
- 30多条mysql数据库优化方法,千万级数据库记录查询轻松解决(转载)
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
- SQL多表合并查询结果
两表合并查询,并同时展示及分页SELECT a.* FROM ( ( SELECT punycode, `domain`, 'Success' AS state, add_time, AS refun ...
- Oracle数据库的SQL分页模板
在系统开发过程中,需要对数据进行查询,大部分情况下从数据库中查询的数据量比较大,在系统页面无法全部显示,而且查询全部的数据会影响系统的反应速度,需要对所查询的数据进行分页的查询操作,以此减轻系统的压力 ...
- mysql数据库管理工具sqlyog在首选项里可以设置默认查询分页条数和字体,改写关键字大小写
sqlyog设置一直习惯用sqlyog来管理mysql数据库,但有三个地方用得不是很爽:1.默认查询条数只有1000条经常需要勾选掉重新查询.2.自动替换关键字大小写,有时候字段名为关键字的搞成大写的 ...
- [R语言]foreach和doParallel包实现多个数据库同时查询
R语言在进行数据库查询时,每执行一条语句,都会阻塞.直到查询语句返回结果之后,才会进行下一条语句. 为了能够实现同时对多个数据库进行查询,以节省顺序执行下来的时间,首先考虑通过多线程来进行数据库查询. ...
随机推荐
- Java虚拟线程探索
在Java 21中,引入了虚拟线程,这是一个非常非常重要的特性,之前一直苦苦寻找的Java协程,终于问世了.在高并发以及IO密集型的应用中,虚拟线程能极大的提高应用的性能和吞吐量. ## 什么是虚拟线 ...
- Q:jar包启动脚本备份
jarServer.sh #!/bin/bash #APP_NAME必须配置. cd `dirname $0` cd .. DEPLOY_DIR=`pwd` APP_HOME=$DEPLOY_DIR/ ...
- AGC043E
抄一下 https://www.luogu.com.cn/article/n32presk,写的非常好. 下面是要把问题转化为一个群论问题. 定义拓扑空间:全集 \(X\) 和它的一个子集族 \(T\ ...
- Codeforces Round 999 比赛记录
前情提要 这个菜鸡CF上了 \(\color{darkcyan}Specialist\),心情大好,正好赶上放假,决定打一场CF. 赛时记录 A 上来脑子抽了,吃了一发罚时.发现写错了一种情况,改过来 ...
- QT5笔记: 29. 文本文件读写
例子:主要讲了 QFile .QTextStream 进行文本文件读写 MainWindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include ...
- Typecho防黑安全加固-修改后台路径
删除安装文件 成功安装后删除install.php文件.install/文件夹. 修改后台地址 把admin修改为黑客猜不到的名字,例如pipixia,防止黑客穷举密码. 修改admin文件夹名称 修 ...
- Ansible - [08] 模块应用
firewalld 模块 使用firewalld模块可以配置防火墙策略 [root@control ~]# cat ~/ansible/firewall.yml --- - hosts: agent ...
- 理解Rust引用及其生命周期标识(上)
写在前面 作为Rust开发者,你是否还没有完全理解引用及其生命周期?是否处于教程一看就会,但在实际开发过程中不知所措?本文将由浅入深,手把手教你彻底理解Rust引用与生命周期. 关于本文的理解门槛 本 ...
- 使用QT开发远程linux服务器过程
1.添加设备为通用linux 2.设置ip用户名 3.创建私钥文件,原来有的qtc那俩个文件删掉. 4.部署公钥,前提是测试链接要出现成功 5.在kits里添加编译环境设置编译器为32位或者64 6. ...
- 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
昨天DD以为阿里开源的QwQ-32B会刷爆全网,毕竟对标的是上一个热门项目deepseek-r1.但是,万万没想到,获得更多关注的居然是:Manus. 简单的从网上介绍信息了解了一下,感觉跟OpenA ...