如何遍历API响应的分页数据并将其保存至数据库?
解决API分页数据遍历与数据库存储问题
看起来你遇到的核心问题有两个:无法获取API的总页数,以及硬编码分页循环不生效。咱们一步步来解决:
1. 先搞定总页数的获取
你提到在响应头里找不到总页数,那大概率API把分页元数据(总条目数/总页数)放在了响应内容里,而不是HTTP头中。现在你的GetTrips类只定义了page、page_size和items,需要先确认API返回的完整响应结构——比如用Postman调用一次trips?page=1,看看响应里有没有类似total_items(总条目数)或者total_pages(总页数)的字段。
假设API返回的是total_items,那先更新你的GetTrips类:
public class GetTrips { public int page { get; set; } public int page_size { get; set; } public int total_items { get; set; } // 新增:对应API返回的总条目数 public Item[] items { get; set; } }
如果API直接返回total_pages,那就把total_items换成total_pages即可,后续不用计算总页数。
2. 修复分页遍历逻辑
你之前硬编码i<5不生效,大概率是因为API的页码是从1开始的(很多API都是1-based),而你循环从i=0开始,请求的page=0可能没有数据,导致后续逻辑失效。另外,每次调用CallAPI都新建HttpClient是不好的实践,会耗尽连接池,要复用它。
修改后的完整代码
第一步:复用HttpClient
把HttpClient声明为静态字段,避免重复创建:
// 全局复用HttpClient,不要每次调用都new private static readonly HttpClient _httpClient = new HttpClient(); private static async Task<GetTrips> CallAPI(string endpoint, string accessToken) { var request = new HttpRequestMessage(HttpMethod.Get, new Uri(ApiUri, endpoint)); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var response = await _httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); var responseStream = await response.Content.ReadAsStreamAsync(); var responseObject = await JsonSerializer.DeserializeAsync<GetTrips>(responseStream); return responseObject; }
第二步:正确遍历所有分页
先请求第一页获取总页数,再循环遍历所有页面:
private static async Task SaveData(string accessToken) { MSSQL_Conn conn = new MSSQL_Conn(conn_string); // 先获取第一页数据,拿到分页元数据 var firstPage = await CallAPI("trips?page=1", accessToken); if (firstPage == null || firstPage.items == null || firstPage.total_items == 0) { // 没有数据,直接返回 return; } // 计算总页数:总条目数 ÷ 每页大小,向上取整 int totalPages = (int)Math.Ceiling((double)firstPage.total_items / firstPage.page_size); // 保存第一页数据 var firstPageTrips = firstPage.items.Select(s => new Trips { TripID = s.id, VehicleId = s.vehicle }); // 写入数据库的代码(比如conn.InsertBatch(firstPageTrips);) // 循环遍历剩下的页面(从第2页到最后一页) for (int page = 2; page <= totalPages; page++) { var currentPage = await CallAPI($"trips?page={page}", accessToken); if (currentPage?.items == null) { // 当前页无数据,跳过避免空引用 continue; } var trips = currentPage.items.Select(s => new Trips { TripID = s.id, VehicleId = s.vehicle }); // 写入数据库的相关代码... } }
关键注意点
- 页码起始值:如果你的API是0-based(页码从0开始),那把循环改成从
page=0开始,总页数计算后调整为page < totalPages。 - 错误处理:添加了空值检查,避免因为某一页返回异常导致整个流程崩溃。
- HttpClient复用:这是.NET中调用API的最佳实践,能提升性能并避免连接泄漏问题。
- 硬编码失效的原因:之前你循环从0开始,请求的
page=0可能没有数据,加上总页数不一定是5,所以循环没覆盖到所有有效数据。
内容的提问来源于stack exchange,提问作者mustafa00




