Projections not working along with Data Loaders in HotChocolate v13 Graphql

95 Views Asked by At

I am using EF Core in an ASP.NET Core 8 Web API, these are the 2 entities in my domain:

  1. Batch
  2. Payments

This is how entities looks like :

public class Batch : IEntity
{
    public string InternalId { get; set; }
    public string TenantId { get; set; }
    public string ExternalId { get; set; }
    public List<Payment> Payments { get; set; }
}

public class Payment : IEntity 
{
    public string InternalId { get; set; }
    public string ExternalId { get; set; }
    public decimal Amount { get; set; }
}

I want to write a graphql query to return a Batch and its Payments.

I created 2 types ( Class Based)

public class Batch 
{
    public string TenantId { get; set; }
    public string ExternalId { get; set; }
    public int? PaymentsCount { get; set; }
    public decimal? TotalAmount { get; set; }
    public List<Payment> { get; set; }

    [DataLoader]
    internal static async Task<ILookup<string, Domain.PaymentBatch.PaymentBatch>> PaymentBatches(IReadOnlyList<string> keys,
        PaymentReadOnlyGraphQLContext paymentReadOnlyGraphQlContext, CancellationToken cancellationToken)
    {
        var batches = await paymentReadOnlyGraphQlContext.PaymentBatches
            .Where(x => keys.Contains(x.TenantId))
            .ToListAsync(cancellationToken);
        return batches.ToLookup(x=>x.TenantId)!;
    }
}

public class Payment 
{
    public string ExternalId { get; set; }
    public decimal Amount { get; set; }
    // omitted other fields for brevity
}

Query :

public class BatchesQuery
{
    // Resolver
    [UsePaging(IncludeTotalCount = true)]
    [UseFiltering]
    [UseSorting]
    public async Task<List<Batch>> Batches(IPaymentBatchesDataLoader paymentBatchDataLoader, string tenantId, [Service] ILogger<BatchesQuery> logger)
    {
        try
        {
            var paymentBatches = await paymentBatchDataLoader.LoadAsync(tenantId, CancellationToken.None);
            return paymentBatches.Select(paymentBatch => new Batch()
                {
                    BatchId = paymentBatch.ExternalId,
                    PaymentsCount = paymentBatch.Payments,
                    TotalAmount = paymentBatch.Payments.SelectMany(x => x.RemittanceDetails).Sum(x => x.Net),
                    Payments = paymentBatch.PaymentRequests.Select(x => new Types.Payment()
                            {
                                Id = x.ExternalId,                              
                                Amount = x.RemittanceDetails.Sum(x => x.Net),
                            })
                            .ToList(),
                    TenantId = paymentBatch.TenantId
                })
                .ToList();
        }
        catch (Exception e)
        {
            logger.LogError(e, "Error getting batches");
            return new List<Batch>();
        }
    }
}

I created a Dataloader, query to fetch the data from the database. I expected the response will have the Batches along with the payments. For some reason the payments returned from the dataloaders are always null. I see batch data returned but not the payments.

I don't really understand what's happening. Am I missing anything in the setup ?

Should I create a Payment Query and Dataloader to get payments ?

Should I use Include statement in the batch dataloader like below ?

[DataLoader]
internal static async Task<ILookup<string, Domain.PaymentBatch.PaymentBatch>> PaymentBatches(IReadOnlyList<string> keys,
    PaymentReadOnlyGraphQLContext paymentReadOnlyGraphQlContext, CancellationToken cancellationToken)
{
    var batches = await paymentReadOnlyGraphQlContext.PaymentBatches
        .Where(x => keys.Contains(x.TenantId))
        .Include(b=>b.PaymentRequests)
        .ToListAsync(cancellationToken);
    return batches.ToLookup(x=>x.TenantId)!;
}

I used [UseProjection] annotation on the BatchesQuery but that didn't really help.

Could some please help me what I am missing ? I followed this video https://www.youtube.com/watch?v=72WVRPwzwLk to setup graphql in my API.

0

There are 0 best solutions below