.NET Core Web API分页接收用户数据时如何持久化数据?
解决方案
方案1:基于批次ID+临时存储(推荐,支持多实例部署)
核心思路是让客户端先发起同步初始化请求获取唯一批次ID,后续每一页数据提交时都携带该ID。服务端以批次ID为标识,将各页数据暂存到Redis、数据库临时表等分布式存储中,收到最后一页时汇总该批次下的所有数据统一处理。
实现步骤:
- 添加同步初始化接口生成批次ID:
[HttpPost("InitUserSync")] public async Task<IActionResult> InitUserSync() { var batchId = Guid.NewGuid().ToString(); // 可选:初始化批次记录到数据库,用于跟踪同步状态、超时清理 await _tempBatchRepo.CreateBatchAsync(batchId); return Ok(new { BatchId = batchId }); }
- 修改原接口,接收批次ID并暂存数据:
[HttpPost("SyncroniseUsers")] public async Task<IActionResult> SyncroniseUsers([FromBody] UserPageDataWithBatch userPageData) { // 验证批次ID有效性 var validBatch = await _tempBatchRepo.IsBatchValidAsync(userPageData.BatchId); if (!validBatch) { return BadRequest("无效批次ID,请先初始化同步"); } // 将当前页数据存入临时存储(示例用Redis,也可替换为数据库临时表) await _redisClient.ListRightPushAsync($"user_sync:{userPageData.BatchId}", JsonSerializer.Serialize(userPageData.UserData)); if(userPageData.IsLastPage) { // 汇总该批次所有数据 var allPageJson = await _redisClient.ListRangeAsync($"user_sync:{userPageData.BatchId}"); var allUsers = allPageJson.Select(json => JsonSerializer.Deserialize<User[]>(json)) .SelectMany(u => u) .ToList(); // 执行计算并写入正式数据库 await _userRepo.BulkSaveUsersAsync(allUsers); // 清理临时数据 await _redisClient.KeyDeleteAsync($"user_sync:{userPageData.BatchId}"); await _tempBatchRepo.MarkBatchCompletedAsync(userPageData.BatchId); return Ok(new { Message = "同步完成", TotalUsers = allUsers.Count }); } return Ok(new { Message = "当前页数据已接收" }); } // 扩展请求模型,增加批次ID字段 public class UserPageDataWithBatch : UserPageData { public string BatchId { get; set; } }
- Windows服务调用流程:
- 先调用
InitUserSync获取批次ID - 逐页提交数据,每次携带该批次ID
- 最后一页设置
IsLastPage=true
- 先调用
方案2:使用ASP.NET Core Session(仅单实例部署场景)
如果API是单实例部署,可以利用Session暂存数据。需先配置Session服务:
配置Session:
在Program.cs中添加:
builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromHours(1); // 设置足够完成同步的超时时间 options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); // 注册Session中间件(需放在UseRouting之后,UseEndpoints之前) app.UseSession();
修改接口:
[HttpPost("SyncroniseUsers")] public async Task<IActionResult> SyncroniseUsers([FromBody] UserPageData userPageData) { // 从Session获取已暂存的用户列表,不存在则初始化 var storedUsers = HttpContext.Session.Get<List<User>>("SyncUsers") ?? new List<User>(); storedUsers.AddRange(userPageData.UserData); if(userPageData.IsLastPage) { // 执行计算并保存到数据库 await _userRepo.BulkSaveUsersAsync(storedUsers); // 清理Session数据 HttpContext.Session.Remove("SyncUsers"); return Ok(new { Message = "同步完成", TotalUsers = storedUsers.Count }); } // 将更新后的列表存入Session HttpContext.Session.Set("SyncUsers", storedUsers); return Ok(new { Message = "当前页数据已接收" }); } // Session序列化/反序列化扩展方法 public static class SessionExtensions { public static void Set<T>(this ISession session, string key, T value) { session.SetString(key, JsonSerializer.Serialize(value)); } public static T Get<T>(this ISession session, string key) { var value = session.GetString(key); return value == null ? default : JsonSerializer.Deserialize<T>(value); } }
注意:Session依赖Cookie,Windows服务调用时需确保HttpClient启用Cookie支持(如设置HttpClientHandler.UseCookies = true)。
方案3:直接批量提交(网络带宽允许时)
如果客户端与API之间带宽充足,可将数千条数据打包为一个请求提交,避免分页逻辑。但数据量过大(如超过100MB)时,仍建议使用批次ID方案。
内容的提问来源于stack exchange,提问作者Imran Yaseen
相关产品推荐
相关产品推荐

