Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

GraphQl query is null

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

    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
            }
        ]
    }
}

>Solution :

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 );
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading