You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Hot Chocolate中用Connection实现偏移分页?

在Hot Chocolate中用Connection实现偏移分页

核心逻辑

官方文档提到Connection的cursor是不透明的,因此可以将偏移量(offset)编码到cursor中,或者直接在Resolver中处理offset参数,最终包装成符合规范的Connection结构。下面是两种实用实现方式:


方式1:直接接收offset/limit参数

这种方式更直观,适合习惯偏移分页的场景:

1. 定义实体与Repository(示例)

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public interface IProductRepository
{
    Task<int> GetTotalCountAsync(CancellationToken ct);
    Task<List<Product>> GetProductsAsync(int offset, int limit, CancellationToken ct);
}

// EF Core实现示例
public class EfProductRepository : IProductRepository
{
    private readonly AppDbContext _dbContext;

    public EfProductRepository(AppDbContext dbContext) => _dbContext = dbContext;

    public async Task<int> GetTotalCountAsync(CancellationToken ct)
        => await _dbContext.Products.CountAsync(ct);

    public async Task<List<Product>> GetProductsAsync(int offset, int limit, CancellationToken ct)
        => await _dbContext.Products.Skip(offset).Take(limit).ToListAsync(ct);
}

2. 编写Query Resolver

public class Query
{
    public async Task<Connection<Product>> GetProductsAsync(
        int offset = 0,
        int limit = 10,
        [Service] IProductRepository repository,
        CancellationToken cancellationToken)
    {
        var totalCount = await repository.GetTotalCountAsync(cancellationToken);
        var products = await repository.GetProductsAsync(offset, limit, cancellationToken);

        // 为每个商品生成cursor:用偏移量+索引编码
        var edges = products.Select((product, index) => new Edge<Product>(
            product,
            CursorSerializer.ToCursor(offset + index)
        )).ToList();

        // 判断分页状态
        var hasPreviousPage = offset > 0;
        var hasNextPage = offset + limit < totalCount;

        // 构造Connection返回
        return new Connection<Product>(
            edges,
            new PageInfo(
                hasPreviousPage,
                hasNextPage,
                edges.FirstOrDefault()?.Cursor,
                edges.LastOrDefault()?.Cursor
            ),
            totalCount
        );
    }
}

方式2:使用标准ConnectionArguments(推荐)

这种方式遵循GraphQL Connection规范,用first(每页数量)和after(上一页最后一个cursor)参数,将cursor解析为偏移量,方便后续切换到游标分页:

编写Resolver

public class Query
{
    public async Task<Connection<Product>> GetProductsAsync(
        ConnectionArguments args,
        [Service] IProductRepository repository,
        CancellationToken cancellationToken)
    {
        // 解析after cursor得到偏移量
        int offset = args.After != null 
            ? CursorSerializer.FromCursor<int>(args.After) + 1 
            : 0;
        int limit = args.First ?? 10;

        // 后续逻辑与方式1一致
        var totalCount = await repository.GetTotalCountAsync(cancellationToken);
        var products = await repository.GetProductsAsync(offset, limit, cancellationToken);

        var edges = products.Select((product, index) => new Edge<Product>(
            product,
            CursorSerializer.ToCursor(offset + index)
        )).ToList();

        var hasPreviousPage = offset > 0;
        var hasNextPage = offset + limit < totalCount;

        return new Connection<Product>(
            edges,
            new PageInfo(
                hasPreviousPage,
                hasNextPage,
                edges.FirstOrDefault()?.Cursor,
                edges.LastOrDefault()?.Cursor
            ),
            totalCount
        );
    }
}

服务注册

确保在Startup/Program.cs中注册GraphQL服务并启用Connection支持:

builder.Services.AddScoped<IProductRepository, EfProductRepository>();

builder.Services
    .AddGraphQLServer()
    .AddQueryType<Query>()
    .AddType<ProductType>() // 若自定义Product的GraphQL类型则添加
    .AddConnectionType<ProductConnection>(); // 自动生成Product的Connection类型

关键说明

  • CursorSerializer是Hot Chocolate内置工具,负责将整数偏移量编码/解码为符合规范的不透明base64 cursor。
  • 分页状态判断:hasPreviousPage基于offset是否大于0,hasNextPage基于当前页结束位置是否小于总数量。
  • 若不需要总数量,可省略totalCount参数(Connection构造函数支持可选总数)。

内容的提问来源于stack exchange,提问作者van9petryk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 08:56:01