GraphQL 查询为空

GraphQL query is null

我正在使用 graphQL 热巧克力,需要获取数据。 我需要从具有规范的模板中获取数据,并且在规范中它包含 AttributeType。 当我尝试查询数据时,模板和规范有值,但 AttributeType 为 null,这是不应该的。 这是我的实体:

模板

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

规格

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

最后是 AttributeType

public         long            Id          { get; set; }
public         string          Description { get; set; }
public         string          Format      { get; set; }

我使用了数据加载器和解析器来获取数据

[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;
}

当我查询 GetTemplateById 时,我得到了结果,但是 AttributeType 为 null,这不应该是,这里是一个查询示例:

"data": {
    "templatebyId": {
        "name": "test",
        "specs": [
            {
                "id": 4,
                "position": 0,
                "label": "price",
                "templateId": 1,
                "attributeType": null
            }
        ]
    }
}

默认情况下,EF 会尝试优化从数据库中获取的数据量。正如您现在的代码一样,未加载属性。

您应该在此调用中包含 attributes,或者省略 ToListAsync 让 EF 确定您在稍后阶段需要数据。

var result = await _dbContext.Templates
                               .Where( template => keys.Contains( template.Id ) )
                               .Select( x => new {
                                                   TemplateId= x.Id,
                                                   x.Specs
                                                 } )
                               .ToListAsync( cancellationToken: cancellationToken );

使用 Include/ThenInclude 将告诉框架包含数据:

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 );