Dapper分批处理大量数据需手动实现分页查询或流式读取,避免内存溢出;推荐OFFSET-FETCH分页(小偏移)或游标分页(大偏移),配合IAsyncEnumerable流式处理、参数化批量写入及每批独立事务+断点续跑机制。

用 Dapper 分批处理大量数据,核心是避免一次性加载全部结果到内存,同时保持数据库连接轻量、SQL 高效。关键在于手动分页查询、流式读取(QueryAsync<t></t> + IAsyncEnumerable<t></t>)或配合 SQL 的分页/游标机制,而不是依赖 Dapper 自动“分批”——它本身不提供内置的批量分片能力。
使用 OFFSET-FETCH 或 ROW_NUMBER 实现服务端分页
适合数据有序、可预估总条数的场景(如按 ID 或时间排序)。每次只查一页,减少单次内存占用和网络传输压力。
- SQL 示例(SQL Server):
SELECT * FROM Orders WHERE Status = @status ORDER BY Id OFFSET @skip ROWS FETCH NEXT @take ROWS ONLY - C# 调用时循环执行,每次更新
@skip(如 0, 1000, 2000…),@take建议 500–5000,视单行大小和网络延迟调整 - 注意:OFFSET 越大性能越差,超 10 万行建议改用游标(keyset pagination),例如
WHERE Id > @lastId ORDER BY Id LIMIT @take
用 IAsyncEnumerable 流式读取(.NET 5+)
避免把整张表拉进 List
- 写法示例:
await foreach (var order in connection.QueryAsync("SELECT * FROM Orders WHERE ...")) { Process(order); } - 底层复用 DataReader,不缓存全部结果;但要求连接保持打开,且业务逻辑不能跨 await 长时间阻塞
- 适合 ETL、导出、校验类任务;不适合需要随机访问或多次遍历的场景
批量写入:用 ExecuteAsync + 参数化 IN 或临时表
Dapper 不直接支持批量 INSERT,需自己拼 SQL 或借助扩展(如 Dapper.FastCRUD);但安全高效的做法仍是分组 + 参数化。
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。
还木有评论哦,快来抢沙发吧~