【问题标题】:Using projections without returning IQueryable, GraphQL HotChocolate使用投影而不返回 IQueryable、GraphQL HotChocolate
【发布时间】:2022-01-10 23:06:13
【问题描述】:

如果我不希望我的服务返回 IQueryable,有没有办法使用预测?

我正在考虑类似的事情,我的解析器可以将输入映射到表达式,然后调用服务类,然后根据提供的表达式构建和执行查询,转换为一些只读集合并返回给用户。

类似于以下内容:

 public async Task<IReadOnlyList<TestPayload>> GetAllTests(
                                             [Service] ITestService, 
                                             CancellationToken cancellationToken, 
                                             object[] requestedFields) => 
            await service.GetAllAsync(requestedFields, cancellationToken);

然后为我服务:

var expression = BuildExpression(requestedFields);

var output = testRepository.Queryable()
                                 .Select(expression)
                                    .AsNoTracking();
return output.ToListAsync();

你能告诉我一些关于这个的方向吗?


编辑:

根据@Pascal 的回答,我在 IQueryable 上添加了 HotChocolate.Data 包并调用了 Project(context) 扩展方法。

现在我的有效负载(模型)类有问题,但我不太确定原因。

以下示例将返回所有列并且不会应用投影。

       [UseProjection]
       public async Task<IReadOnlyList<TestPayload>> TestGetAll([Service] ITestService testService, IResolverContext context, CancellationToken cancellationToken) 
        {
            return await testService.GetAllAsync(context, cancellationToken);
        }

这个会起作用,并且会投射到查询中并只返回请求的内容。请注意,唯一不同的是返回类型(IReadOnly 而不是 IReadOnly)。

       [UseProjection]
       public async Task<IReadOnlyList<Test>> TestGetAll([Service] ITestService testService, IResolverContext context, CancellationToken cancellationToken) 
        {
            return await testService.GetAllAsync(context, cancellationToken);
        }

服务内部:

var tests = testRepository.Queryable()
                         .Project<Test>(context)
                        .AsNoTracking();

我猜这是因为解析器现在正在使用 dto TestPayload 类型,然后在服务内部尝试投影到实体(测试)的 IQueryable,但我不确定如何克服它。

【问题讨论】:

  • 这方面有什么更新吗?

标签: c# entity-framework asp.net-core graphql hotchocolate


【解决方案1】:

是的,HotChocolate.Data 在 IQueryable 之上提供了扩展方法

 public async Task<IReadOnlyList<TestPayload>> GetAllTests(
    [Service] ITestService, 
    CancellationToken cancellationToken, 
    IResolverContext context) => 
    await service.GetAllAsync(context, cancellationToken);
var output = testRepository.Queryable()
     .Project(context)
     .AsNoTracking();
return output.ToListAsync();

【讨论】:

  • 很好,但是由于某些奇怪的原因,当我从服务返回 dto 时它不起作用,而当返回类型为实体时它就很好。我检查了查询并注意到 .Project(context) 在这种情况下被忽略了,所以我把所有的列都拿回来了。也许我错过了一些明显的东西,我正在调查它。所以在上面的例子中,当返回类型是TestPayload时,它不会起作用,但是如果我把它切换到Test(这是我的实体类)就很好了。
  • 我已将此添加到问题编辑中。因为我不希望我的服务返回实体,所以保留 DTO 的最佳方法是什么?我知道 DTO 可能是一种反模式,但我可能会将我的服务用于 GraphQL 以外的其他事情。
  • 你能提供一个链接来阅读这个吗?
猜你喜欢
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-17
  • 2019-08-28
  • 1970-01-01
  • 2021-07-16
相关资源
最近更新 更多