c# - 是否可以在 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; }
}
知道问题是什么吗?
谢谢
解决方案
推荐阅读
- logging - 尝试将通用 CEF 日志转发到 Azure Sentinel
- php - 检查 Zip 文件是否使用 PHP 加密或密码保护
- python - 如何更好地理解“最长有效括号”问题的解决方案?
- javascript - Woocommerce 重定向到已添加产品的购物车
- f# - 如何将需要操作的初始化代码转换为 F#
- powershell - powershell Receive-Job 查找状态是否失败
- mysql - mysql GROUP BY 太慢了。有什么帮助让它更快吗?
- sql - 按键比较行中的两个值,然后有条件地向表中添加一些东西?
- node.js - 扩展请求类型以添加 Redis 客户端
- javascript - 任务从未定义:browserSync.reload