1

我正在尝试通过一个非常简单的 graphql 服务器示例并进行选择。

https://www.blexin.com/en-US/Article/Blog/Creating-our-API-with-GraphQL-and-Hot-Chocolate-79

(没有 SQL 后端,我想了解它端到端,所以这在内存数据表中)。

我已经按照演练实现了它(某些属性,例如“[UseFiltering]”不编译,我暂时将它们注释掉)。

我的启动看起来像这样

        services.AddSingleton<IAuthorService, InMemoryAuthorService>();
        services.AddSingleton<IBookService, InMemoryBookService>();

        services.
            AddGraphQLServer().
            AddType<AuthorType>().
            AddType<BookType>().
            AddQueryType<GraphQL.Query>();

看起来很奇怪的是当我试图询问一本书的作者时

{
  books {
    title
    authorId
    price
    author { 
      name
      surname 
    }
  }
}

香蕉蛋糕流行抱怨

field author argument book of type BookInput! is required

(如果我不要求作者,那么一切都很好)

booktype 看起来像这样(根据演练)

public class BookType : ObjectType<Book>
{
    protected override void Configure(IObjectTypeDescriptor<Book> descriptor)
    {
        descriptor.Field(b => b.Id).Type<IdType>();
        descriptor.Field(b => b.Title).Type<StringType>();
        descriptor.Field(b => b.Price).Type<DecimalType>();
        descriptor.Field<AuthorResolver>(t => t.GetAuthor(default, default));
    }
}

作者解析器看起来像这样

public class AuthorResolver
{
    private readonly IAuthorService _authorService;

    public AuthorResolver([Service]IAuthorService authorService)
    {
        _authorService = authorService;
    }

    public Author GetAuthor(Book book, IResolverContext ctx)
    {
        return _authorService.GetAll().Where(a => a.Id == book.AuthorId).FirstOrDefault();
    }
}

再次,根据演练。

我基本上理解错误,但我无法理解这应该如何工作,不知何故,“书”父母必须进入 AuthorResolver 上的 GetAuthor 方法......我错过了一些魔法,或者 v11 是缺少一些魔法。

附言

我更喜欢声明性类型的表达式,而不是反身魔法......所以也许我错过了一些东西

4

2 回答 2

1

问题是我的 AuthorResolver 上的 GetAuthor 方法缺少“父”属性,以触发一些魔法......

    public Author GetAuthor([Parent]Book book, IResolverContext ctx)
    {
        return _authorService.GetAll().Where(a => a.Id == book.AuthorId).FirstOrDefault();
    }

理想情况下,我想删除这个自定义属性魔法。

于 2020-11-27T14:16:36.937 回答
0

实际上,当前版本 11.0.9 不需要 [Parent] 属性。我特别检查了解析器类。但是在下面的示例中,我删除了解析器,因为在您的情况下使用它太冗长了。此外,我删除了 Book 参数以显示从解析器上下文获取该参数的方法。

using System.Linq;
using HotChocolate.Resolvers;
using HotChocolate.Types;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Ademchenko.GraphQLWorkshop
{
    public class Author
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
    }

    public class Book
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public int AuthorId { get; set; }
        public decimal Price { get; set; }
    }

    public interface IAuthorService { IQueryable<Author> GetAll(); }

    public interface IBookService { IQueryable<Book> GetAll(); }

    public class InMemoryAuthorService : IAuthorService
    {
        private readonly Author[] _staticAuthors = {
            new Author {Name = "FooAuthor", Surname = "FooSurname", Id = 1},
            new Author {Name = "BarAuthor", Surname = "BarSurname", Id = 2},
        };

        public IQueryable<Author> GetAll() => _staticAuthors.AsQueryable();
    }

    public class InMemoryBookService : IBookService
    {
        private readonly Book[] _staticBooks = {
            new Book {Id = 11, Title = "FooBook", AuthorId = 1, Price = 10.2m},
            new Book {Id = 22, Title = "BarBook", AuthorId = 2, Price = 20.2m},
        };

        public IQueryable<Book> GetAll() => _staticBooks.AsQueryable();
    }

    public class Query
    {
        public IQueryable<Book> GetBooks(IResolverContext ctx) => ctx.Service<IBookService>().GetAll();
    }

    public class BookType : ObjectType<Book>
    {
        protected override void Configure(IObjectTypeDescriptor<Book> descriptor)
        {
            descriptor.Field(b => b.Id).Type<IdType>();
            descriptor.Field("author").Resolve((ctx, ct) => ctx.Service<IAuthorService>().GetAll().FirstOrDefault(a => a.Id == ctx.Parent<Book>().AuthorId));
        }
    }

    public class Startup
    {
        public IConfiguration Configuration { get; }

        public Startup(IConfiguration configuration) => Configuration = configuration;

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddSingleton<IAuthorService, InMemoryAuthorService>();
            services.AddSingleton<IBookService, InMemoryBookService>();

            services.AddGraphQLServer()
                .AddQueryType<Query>()
                .AddType<BookType>();
        }
        
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env) => app.UseRouting().UseEndpoints(endpoints => endpoints.MapGraphQL());
    }
}

这是一个完整的示例,因此如果您向端点发出以下请求:

{
  books
  {
    id,
    title
    authorId    
   author    
    {
      id
      name            
    }
  } 
}

你会得到:

{
  "data": {
    "books": [
      {
        "id": "11",
        "title": "FooBook",
        "authorId": 1,
        "author": {
          "id": 1,
          "name": "FooAuthor"
        }
      },
      {
        "id": "22",
        "title": "BarBook",
        "authorId": 2,
        "author": {
          "id": 2,
          "name": "BarAuthor"
        }
      }
    ]
  }
}
于 2021-03-06T21:43:39.233 回答