Skip to main content

DataLoader

DataLoaders are a foundational concept in GraphQL and allow us to coalesce multiple requests for the same entity into a single request. This is especially useful when we have a list of entities and need to fetch related entities for each of them. Without a DataLoader, we would have to make a separate request for each entity, which can lead to the N+1 problem.

DataLoader in Hot Chocolate

In Hot Chocolate, we can implement a class-based DataLoader by inheriting from the DataLoaderBase<TKey, TValue> class. It also offers more specialized DataLoader base classes like the BatchDataLoader<TKey, TValue>.

public sealed class ProductByIdDataLoader : BatchDataLoader<int, ProductInfo>, IProductByIdDataLoader
{
public ProductByIdDataLoader(
Func<HttpClient> clientFactory,
IBatchScheduler batchScheduler,
DataLoaderOptions options)
: base(batchScheduler, options)
{
}
}

But Hot Chocolate also provides a DataLoader to remove boilerplate code from less complex DataLoader implementations:

internal static class ProductDataLoader
{
[DataLoader]
public static async Task<Dictionary<int, Product>> GetProductByIdAsync(
IReadOnlyList<int> ids,
CatalogContext context,
CancellationToken ct)
=> await context.Products
.AsNoTracking()
.Where(t => ids.Contains(t.Id))
.ToDictionaryAsync(t => t.Id, ct);
}

In the above example, the DataLoader is basically reduced to its fetch method, and the class with DI logic is generated by the source generator.