I am using EF Core in an ASP.NET Core 8 Web API, these are the 2 entities in my domain:
- Batch
- 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.