I'm using graphQL hot chocolate and need to fetch data. I need to fetch data from Template that has Specs and in spec it contains AttributeType. when i try to query the data, template and spec has values but AttributeType is null that should not be. here are my entities:
Template
public long Id { get; set; }
public bool IsDeleted { get; set; }
public string Name { get; set; }
public long SpecId { get; set; }
public virtual List<Spec> Specs { get; set; }
Spec
public long Id { get; set; }
public int Position { get; set; }
public string Label { get; set; }
public bool IsDeleted { get; set; }
public virtual AttributeType AttributeType { get; set; }
public long AttributeTypeId { get; set; }
public Template Template { get; set; }
public long? TemplateId { get; set; }
and finally AttributeType
public long Id { get; set; }
public string Description { get; set; }
public string Format { get; set; }
I used Dataloader and resolver to fetch the data
[Authorize]
[GraphQLType( typeof(TemplateObjectType) )]
public Task<Template> GetTemplateById( long id, TemplateDataLoader dataLoader, CancellationToken cancellationToken )
=> dataLoader.LoadAsync( id, cancellationToken );
public class TemplateObjectType: ObjectType<Template>
{
protected override void Configure( IObjectTypeDescriptor<Template> descriptor )
{
descriptor.Field( x => x.Specs)
.ResolveWith<TemplateResolver>( r => r.GetSpecsAsync( default, default, default ) );
}
}
public async Task<IReadOnlyList<Spec>> GetSpecAsync(
[Parent] Template template,
SpecDataLoader dataLoader,
CancellationToken cancellationToken)
=> await dataLoader.LoadAsync(template.Id, cancellationToken);
protected override async Task<ILookup<long, Spec>> LoadGroupedBatchAsync( IReadOnlyList<long> keys, CancellationToken cancellationToken )
{
var result = await _dbContext.Templates
.Where( template => keys.Contains( template.Id ) )
.Select( x => new {
TemplateId= x.Id,
x.Specs
} )
.ToListAsync( cancellationToken: cancellationToken );
var final = result
.Select(x => x.Specs.Select(c => new
{
x.TemplateId,
Spec= c
}))
.SelectMany(x => x)
.ToLookup(x => x.TemplateId, x => x.Spec);
return final;
}
When I query GetTemplateById I get the result but AttributeType is null which shouldn't be, here is a sample of the query:
"data": {
"templatebyId": {
"name": "test",
"specs": [
{
"id": 4,
"position": 0,
"label": "price",
"templateId": 1,
"attributeType": null
}
]
}
}
CodePudding user response:
By default EF tries to optimize the amount of data fetched from the database. As your code is now, the attributes are not loaded.
You should either include the attributes
in this call, or omit the ToListAsync
to have EF determine you'll need the data in a later stage.
var result = await _dbContext.Templates
.Where( template => keys.Contains( template.Id ) )
.Select( x => new {
TemplateId= x.Id,
x.Specs
} )
.ToListAsync( cancellationToken: cancellationToken );
Using Include/ThenInclude will tell the framework to include the data:
var result = await _dbContext.Templates
.Where( template => keys.Contains( template.Id ) )
.Include(prop => prop.Specs)
.ThenInclude(spec => spec.AttributeType)
.Select( x => new {
TemplateId= x.Id,
x.Specs
} )
.ToListAsync( cancellationToken: cancellationToken );