首页 > 解决方案 > 是否可以在 HotChocolate 中创建通用数据加载器?

问题描述

我正在尝试为我以通用方式提供的任何实体创建具有标准查询和突变的 graphql 服务器,即我从某处读取配置,在内存中创建实体,然后创建 graphql 服务器。

我目前能够创建一个通用类型来查询所有详细信息,但我似乎无法创建一个通用数据加载器来有效地按 Id 检索记录。

query GetSpecificSpeakerById {
  byId(id: 1) {
    name
  }
}

或者

query GetSpecificSpeakerById {
  a: byId(id: 1) {
    name
  }
  b: byId(id: 2) {
    name
  }
}

架构似乎正确生成,但在执行查询时我收到以下信息:

{
  "name": "ServerError",
  "statusCode": 500,
  "statusText": "Internal Server Error",
  "bodyText": "{\"errors\":[{\"message\":\"The ID \\u00601\\u0060 has an invalid format.\"}]}"
}

我目前有以下代码:

启动.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddPooledDbContextFactory<ApplicationDbContext>(options => 
            options.UseSqlite("Data Source=conferences.db"));

        var entityType = typeof(Speaker);            
        Type queryType = typeof(GenericQuery<>).MakeGenericType(entityType);

        Type dataLoaderType = typeof(GenericrByIdDataLoader<>).MakeGenericType(entityType);

        services
                .AddGraphQLServer()
                .AddQueryType(queryType)
                .AddDataLoader<GenericrByIdDataLoader<Speaker>>();                   
    }

GenericByIdDataLoader.cs

public class GenericrByIdDataLoader<TEntity> : BatchDataLoader<int, TEntity>
        where TEntity : class, IEntity
    {
        private readonly IDbContextFactory<ApplicationDbContext> _dbContextFactory;

        public GenericrByIdDataLoader(
            IBatchScheduler batchScheduler,
            IDbContextFactory<ApplicationDbContext> dbContextFactory)
            : base(batchScheduler)
        {
            _dbContextFactory = dbContextFactory ??
                throw new ArgumentNullException(nameof(dbContextFactory));
        }

        protected override async Task<IReadOnlyDictionary<int, TEntity>> LoadBatchAsync(
            IReadOnlyList<int> keys,
            CancellationToken cancellationToken)
        {
            await using ApplicationDbContext dbContext =
                _dbContextFactory.CreateDbContext();

            return await dbContext.Set<TEntity>()
                .Where(s => keys.Contains(s.Id))
                .ToDictionaryAsync(t => t.Id, cancellationToken);
        }
    }

通用查询.cs

public class GenericQuery<TEntity> 
    where TEntity : class, IEntity
{       
    [UseApplicationDbContext]
    public async Task<List<TEntity>> GetAll([ScopedService] ApplicationDbContext context)
    {
        return await context.Set<TEntity>().AsNoTracking().ToListAsync();
    }

    public Task<TEntity> GetByIdAsync(
        [ID(nameof(TEntity))] int id,
        GenericrByIdDataLoader<TEntity> dataLoader,
        CancellationToken cancellationToken)
    {
        return dataLoader.LoadAsync(id, cancellationToken);
    }
}

IEntity.cs

public interface IEntity
    {
        int Id { get; set; }
    }

扬声器.cs

public class Speaker : IEntity
    {
        public int Id { get; set; }

        [Required]
        [StringLength(200)]
        public string? Name { get; set; }

        [StringLength(4000)]
        public string? Bio { get; set; }

        [StringLength(1000)]
        public virtual string? WebSite { get; set; }
    }

知道问题是什么吗?

谢谢

标签: c#asp.net-coregraphqlhotchocolate

解决方案


推荐阅读