HotChocolate v13中Projection与Data Loader配合失效问题
问题:ASP.NET Core 8 Web API中GraphQL返回Batch但关联Payments始终为null
背景
在ASP.NET Core 8 Web API中使用EF Core,领域模型包含Batch和Payment两个实体,希望通过GraphQL查询返回Batch及其关联的Payment列表,但目前仅Batch数据正常返回,Payments始终为null。
领域实体定义
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; } }
GraphQL类型定义
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> Payments { 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; } // 省略其他字段 }
查询定义
public class BatchesQuery { [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() { ExternalId = paymentBatch.ExternalId, PaymentsCount = paymentBatch.Payments?.Count, TotalAmount = paymentBatch.Payments?.SelectMany(x => x.RemittanceDetails).Sum(x => x.Net), Payments = paymentBatch.PaymentRequests.Select(x => new Types.Payment() { ExternalId = x.ExternalId, Amount = x.RemittanceDetails.Sum(x => x.Net), }) .ToList(), TenantId = paymentBatch.TenantId }) .ToList(); } catch (Exception e) { logger.LogError(e, "获取批处理数据出错"); return new List<Batch>(); } } }
当前问题与疑问
- 已通过Data Loader从数据库获取
Batch数据,但关联的Payments始终为null - 不确定是否遗漏配置项,是否需要单独为
Payment创建查询和Data Loader - 考虑在Batch的Data Loader中添加
Include(b=>b.PaymentRequests),但不确定是否正确 - 已在
BatchesQuery上添加[UseProjection]特性,问题仍未解决
解决方案
1. 修复EF Core关联数据加载问题
EF Core默认不会自动加载关联实体(除非开启懒加载,不推荐生产环境使用),必须在查询中通过Include显式指定要加载的关联数据。注意要和领域模型中的属性名保持一致,如果实际关联属性是Payments就用Include(b=>b.Payments),如果是PaymentRequests则对应修改:
[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.Payments) // 显式加载关联的Payment数据 .ToListAsync(cancellationToken); return batches.ToLookup(x => x.TenantId)!; }
2. 修正代码中的语法与映射错误
- 原GraphQL的
Batch类中List<Payment> { get; set; }存在语法错误,需补充属性名Payments - 查询中
PaymentsCount = paymentBatch.Payments类型不匹配,应改为paymentBatch.Payments?.Count - 确认领域模型中的关联属性名和查询中使用的
PaymentRequests是否一致,命名不一致会导致赋值失败
3. 确认GraphQL类型配置
确保Payments字段在GraphQL的Batch类型中被正确注册,未被忽略。如果使用Hot Chocolate框架,需确认类型被正确扫描,或通过显式配置声明字段。
4. Data Loader使用说明
当前场景下不需要单独为Payment创建Data Loader,通过Include加载关联数据即可满足需求。后续若有批量查询Payment的场景,再考虑单独实现对应的Data Loader。
内容的提问来源于stack exchange,提问作者vamsi krishna
相关产品推荐
相关产品推荐

