问题描述
我是 graphql 的新手,目前正在参加 ChilliCream graphql 研讨会。遵循this
后实现分页后有一条注释:“在我们使用 TrackType 的实现中有一个警告。因为,我们在解析器中使用了 DataLoader 并首先获取 ID 列表,所以我们基本上将始终获取所有内容并切入内存。在一个实际的项目,这可以通过将 DataLoader 部分移动到中间件和可查询 id 上的第一页来分为两个操作。也可以实现一个特殊的 IPagingHandler,它使用 DataLoader 并应用分页逻辑。”
我一直无法弄清楚如何拆分这两个操作。任何帮助将不胜感激。
查询
query GetTrackWithSessions {
trackById(id: "VHJhY2sKaTE=") {
id
sessions(first: 1) {
nodes {
title
}
}
}
}
TrackQuery
public Task<Track> GetTrackByIdAsync(
[ID(nameof(Track))] int id,TrackByIdDataLoader trackById,CancellationToken cancellationToken) =>
trackById.LoadAsync(id,cancellationToken);
TrackType
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))
.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);
}
}
谢谢
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)