私はgraphqlを初めて使用し、現在ChilliCream graphqlワークショップに取り組んでいます。これに従ってページングを実装した後
メモがあります:「TrackType を使用した実装には 1 つの注意点があります。リゾルバー内で DataLoader を使用しており、最初に ID のリストをフェッチするため、基本的に常にすべてをフェッチし、メモリをチョップします。実際のプロジェクトではこれは、DataLoader 部分をミドルウェアに移動し、クエリ可能な ID の最初のページに移動することで、2 つのアクションに分割できます。また、DataLoader を使用してページング ロジックを適用する特別な IPagingHandler を実装することもできます。
2 つのアクションを分割する方法がわかりませんでした。どんな助けでも大歓迎です。
クエリ
query GetTrackWithSessions {
trackById(id: "VHJhY2sKaTE=") {
id
sessions(first: 1) {
nodes {
title
}
}
}
}
トラッククエリ
public Task<Track> GetTrackByIdAsync(
[ID(nameof(Track))] int id,
TrackByIdDataLoader trackById,
CancellationToken cancellationToken) =>
trackById.LoadAsync(id, cancellationToken);
トラックタイプ
public class TrackType : ObjectType<Track>
{
protected override void Configure(IObjectTypeDescriptor<Track> descriptor)
{
descriptor
.ImplementsNode()
.IdField(t => t.Id)
.ResolveNode((ctx, id) =>
ctx.DataLoader<TrackByIdDataLoader>().LoadAsync(id, ctx.RequestAborted));
descriptor
.Field(t => t.Sessions)
.ResolveWith<TrackResolvers>(t => t.GetSessionsAsync(default!, default!, default!, default))
.UseDbContext<ApplicationDbContext>()
.UsePaging<NonNullType<SessionType>>()
.Name("sessions");
descriptor
.Field(t => t.Name)
.UseUpperCase();
}
private class TrackResolvers
{
public async Task<IEnumerable<Session>> GetSessionsAsync(
Track track,
[ScopedService] ApplicationDbContext dbContext,
SessionByIdDataLoader sessionById,
CancellationToken cancellationToken)
{
int[] sessionIds = await dbContext.Sessions
.Where(s => s.Id == track.Id)
.Select(s => s.Id)
.ToArrayAsync();
return await sessionById.LoadAsync(sessionIds, cancellationToken);
}
}
}
データローダー
public class TrackByIdDataLoader : BatchDataLoader<int, Track>
{
private readonly IDbContextFactory<ApplicationDbContext> _dbContextFactory;
public TrackByIdDataLoader(
IBatchScheduler batchScheduler,
IDbContextFactory<ApplicationDbContext> dbContextFactory)
: base(batchScheduler)
{
_dbContextFactory = dbContextFactory ??
throw new ArgumentNullException(nameof(dbContextFactory));
}
protected override async Task<IReadOnlyDictionary<int, Track>> LoadBatchAsync(
IReadOnlyList<int> keys,
CancellationToken cancellationToken)
{
await using ApplicationDbContext dbContext =
_dbContextFactory.CreateDbContext();
*All the tracks are returned here
return await dbContext.Tracks
.Where(s => keys.Contains(s.Id))
.ToDictionaryAsync(t => t.Id, cancellationToken);
}
}
ありがとう