Hi, y’all 👋 Season greetings 🎄. In today’s article, I will write about the Hot Chocolate Data Loader feature and how to use it in your ASP.NET server to optimise your database queries.
The data loader in Hot Chocolate helps to prevent your application from the N+1 problem. The N+1 problem occurs when data retrieval that should be done in a single query uses multiple queries to retrieve the same data. This could incur some performance costs in your server application.
For instance, let us look at this sample query.
{
a: author(id: "userId-1") {
name
}
b: author(id: "userId-2") {
name
}
}
Without a data loader, the GraphQL query above will make multiple parallel calls to the database using the query below
-- For Author with ID "userId-1"
SELECT
"a"."Name"
FROM
"Authors" AS "a"
WHERE
"a"."Id" = 'userId-1';
-- For Author with ID "userId-2"
SELECT
"b"."Name"
FROM
"Authors" AS "b"
WHERE
"b"."Id" = 'userId-2';
But with the aid of a data loader, it uses a single query to obtain the same data which could be in either of the forms below
SELECT
"a"."Id",
"a"."Name"
FROM
"Authors" AS "a"
WHERE
"a"."Id" IN (
SELECT
"k"."value"
FROM
json_each('["userId-1", "userId-2"]') AS "k"
);
-- or it can use the query below
SELECT
"a"."Id",
"a"."Name"
FROM
"Authors" AS "a"
WHERE
"a"."Id" IN ("userId-1", "userId-2");
Note: The “userId-1” and “userId-2” in the queries above are placeholders for a GUID string
Let us get started with writing our hot chocolate data loader for the GraphQL query above.
You’ll need to extend the BatchDataLoader generic class
public class AuthorBatchDataLoader : BatchDataLoader<string, Author>
The BatchDataLoader class accepts two generic type parameters. The first is the identifier for the entity and the second is the entity’s type.
Next, is to pass your Database context into your constructor and the IBatchScheduler(which is in charge of differing the data fetching work to a batch dispatcher that will execute the batches).
private readonly ApplicationDbContext _context;
public AuthorBatchDataLoader(
ApplicationDbContext context,
IBatchScheduler batchScheduler)
: base(batchScheduler)
{
this._context = context;
}
Finally, you are to override the LoadBatchAsync method which returns a Task of an IReadOnlyDictionary<key type, entitytype>
protected override async Task<IReadOnlyDictionary<string, Author>> LoadBatchAsync(
IReadOnlyList<string> keys,
CancellationToken cancellationToken)
{
var authors = await _context.Authors
.Where(a => keys.Contains(a.Id))
.ToDictionaryAsync(a => a.Id, cancellationToken);
return authors;
}
The keys parameter in the code above contains a list of all the batched keys that will be used to obtain multiple entity’s data. With that, you can map the returned data into a dictionary which populates the fields in your GraphQL response.
Now, that you’ve seen how to create the data loader for the GraphQL query. The final thing to do is to inject it into your query method.
public async Task<Author?> GetAuthor(string Id, AuthorBatchDataLoader batchDataLoader)
{
return await batchDataLoader.LoadAsync(Id);
}
And that is how easy it is to use a data loader in Hot Chocolate.
To view the entire code used in this post check my GitHub.
To read more about Data Loaders in Hot Chocolate. Check out their website.
Thanks for reading through ………………..bye 👋
Picasso
Wonderful one
Reminder- Transfer №YY84. CONFIRM =>> https://telegra.ph/Go-to-your-personal-cabinet-08-25?hs=056b197eeeebc08f101559a5e926f922&
xsr39l
We send a transaction from us. GЕТ > https://telegra.ph/Go-to-your-personal-cabinet-08-25?hs=056b197eeeebc08f101559a5e926f922&
bevwuv
You have 1 message # 737. Read - https://telegra.ph/Go-to-your-personal-cabinet-08-25?hs=056b197eeeebc08f101559a5e926f922&
6lnfns
We send a transfer from us. Confirm >>> https://telegra.ph/Go-to-your-personal-cabinet-08-25?hs=056b197eeeebc08f101559a5e926f922&
tdh4xe
Ticket- You got a transfer #BS51. LOG IN =>> https://telegra.ph/Go-to-your-personal-cabinet-08-25?hs=056b197eeeebc08f101559a5e926f922&
be7s7w