简体   繁体   English

使用投影而不返回 IQueryable,GraphQL HotChocolate

[英]Using projections without returning IQueryable, GraphQL HotChocolate

Is there a way to use projections if I don't want my services to return IQueryable?如果我不希望我的服务返回 IQueryable,有没有办法使用预测?

I am thinking of something like, my resolver could map input to an Expression and then call the service class, then query is built and executed based on the provided expression, converted to some read only collection and returned to the user.我正在考虑类似的事情,我的解析器可以将 map 输入到表达式,然后调用服务 class,然后根据提供的表达式构建和执行查询,转换为一些只读集合并返回给用户。

Something like the following:类似于以下内容:

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

Then in my service:然后在我的服务中:

var expression = BuildExpression(requestedFields);

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

Can you point me in some direction regarding this?你能给我指出一些关于这个的方向吗?


EDIT:编辑:

As per @Pascal's answer I added HotChocolate.Data package and invoked Project(context) extension method on my IQueryable.根据@Pascal 的回答,我添加了 HotChocolate.Data package 并在我的 IQueryable 上调用了 Project(context) 扩展方法。

Right now I have an issue with my payload(model) classes, but I'm not quite sure why.现在我的有效载荷(模型)类有问题,但我不太清楚为什么。

The following example will return all columns and will not apply projection.以下示例将返回所有列并且不会应用投影。

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

This one will work, and will project to the query and return only what's requested.这将起作用,并将投射到查询并仅返回所请求的内容。 Notice that the only thing that's different is the return type (IReadOnly instead of IReadOnly).请注意,唯一不同的是返回类型(IReadOnly 而不是 IReadOnly)。

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

Inside the service:服务内部:

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

I guess it is because of the resolver that is now working with the dto TestPayload type and then inside the service trying to project to the IQueryable of entity(Test), but I'm not sure how to overcome it.我猜这是因为解析器现在正在使用 dto TestPayload 类型,然后在服务内部尝试投影到实体(测试)的 IQueryable,但我不确定如何克服它。

Yes there is, HotChocolate.Data provides extension methods on top of IQueryable是的,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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM