GraphQL.NET : Как разделить корневой запрос на несколько частей

#asp.net #.net-core #graphql

#asp.net #.net-ядро #graphql

Вопрос:

В настоящее время у меня есть небольшое приложение, которое использует GraphQL для связи с серверной частью .net core. В настоящее время у меня есть один корневой запрос, который является обязательным для GraphQL, и я ищу способ разбить его на несколько частей в интересах организации. Мой запрос выглядит следующим образом:

 public class ReactToFactsQuery : ObjectGraphType
{
    public ReactToFactsQuery(IArticleService articleService,
        INewsItemService newsItemService)
    {
        Field<ArticleType>(
            name: "article",
            arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
            resolve: context =>
            {
                var id = context.GetArgument<int>("id");
                return articleService.Get(id);
            }
        );

        Field<ListGraphType<ArticleType>>(
            name: "articles",
            arguments: new QueryArguments(new QueryArgument<IntGraphType>() { Name = "count" }),
            resolve: context =>
            {
                var count = context.GetArgument<int?>("count");
                if (count.HasValue)
                {
                    return articleService.GetAll(count.Value);
                }
                else
                {
                    return articleService.GetAll();
                }

            }
        );

        Field<ListGraphType<NewsItemType>>(
            name: "newsItems",
            arguments: new QueryArguments(
                new QueryArgument<IntGraphType>() { Name = "count" },
                new QueryArgument<IntGraphType>() { Name = "newsType" }),
            resolve: context =>
            {
                var count = context.GetArgument<int?>("count");
                var category = context.GetArgument<int>("newsType");
                var newsType = (NewsType)category;

                if (count.HasValue)
                {
                    return newsItemService.GetMostRecent(newsType, count.Value);
                }
                else
                {
                    return newsItemService.GetMostRecent(newsType);
                }
            }
        );
    }
}
  

В настоящее время запрос довольно маленький и управляемый, но по мере роста приложения я легко вижу, что в этом классе определено огромное количество запросов. Текущие имена запросов, которые существуют, являются article , articles и newsItems . Предпочтительно, я хотел бы создать класс запросов для представления каждого типа модели (т. Е. один класс запросов для запросов, связанных со статьей, один для запросов, связанных с новостями, и т.д.).

Я прочитал документацию здесь, однако я по какой-то причине изо всех сил пытаюсь понять приведенный здесь пример и как применить его к моему коду.

Любая помощь приветствуется.

Ответ №1:

Как говорится в документации, вы можете разбивать запросы на виртуальные группы следующим образом …

Создание типов вложенных запросов (ArticlesQueryType), которые управляют конкретными запросами.

 public class RootQuery : ObjectGraphType
{
    public RootQuery()
    {
        Name = "RootQuery";
        // defines the articles sub query and returns an empty anonymous type object
        // whose only purpose is to allow making queries on the subtype (ArticlesQueryType)
        Field<ArticlesQueryType>("articles", resolve: context => new {});
    }
}

// defines the articles specific queries
public class ArticlesQueryType: ObjectGraphType
{
    public ArticlesQueryType(IArticleService articleService)
    {
        Name = "ArticlesQuery";
        Field<ArticleType>(
            name: "article",
            arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
            resolve: context =>
        {
            var id = context.GetArgument<int>("id");
            return articleService.Get(id);
        });
    }
}
  

Тип запроса GraphQL будет

 type RootQuery {
  articles: ArticlesQuery
  news: NewsQuery
}

type ArticlesQuery {
   article(id: ID): Article
   articles: [Article]
}
...
  

С другой стороны, если вы не хотите изменять структуру запроса и у вас есть только один корень, который содержит конкретные запросы, вы можете разделить запросы на частичные классы для наглядности …

 public partial class RootQuery: ObjectGraphType
{
    private IArticleService ArticleService { get; }

    public RootQuery()
    {
        Name = "RootQuery";

        InitializeArticlesQueries()
    }
}
  

и в другом файле (RootQuery_Articles.cs), например

 public partial class RootQuery
{
    protected InitializeArticlesQuery()
    {
        Field<ArticleType>(
            name: "article",
            arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
            resolve: context =>
        {
            var id = context.GetArgument<int>("id");
            return articleService.Get(id);
        });
    }
}
  

Таким образом, тип запроса GraphQL является

 type RootQuery {
    articles: [Article]
    ....
}
  

Комментарии:

1. Правильно ли предположение, что вы создаете все запросы Article. Один для getOne, GetAll и т.д. … В ArticlesQueryType?

2. Я бы добавил, что недостатком использования частичных классов является то, что файл RootQuery по-прежнему заполняется длинным списком зависимостей, если вы используете внедрение конструктора. например, если у вас более 100 сервисов или репозиториев, то это будет длинный список

3. И с подходом schema first? Я вижу только, что частичный метод является единственным вариантом здесь…