graphqlgraphql-dotnetgraphql.net

How does one organize more than a few mutations in GraphQL .Net GraphType First?


In GraphQL .Net most of the example code has one top level mutations graph object that has many actual mutations defined within it.
Here's an example from the GraphQL .NET mutations page:

public class StarWarsSchema : Schema
{
  public StarWarsSchema(IServiceProvider provider)
    : base(provider)
  {
    Query = provider.Resolve<StarWarsQuery>();
    Mutation = provider.Resolve<StarWarsMutation>();
  }
}


public class StarWarsMutation : ObjectGraphType
{
  public StarWarsMutation(StarWarsData data)
  {
    Field<HumanType>(
      "createHuman",
      arguments: new QueryArguments(
        new QueryArgument<NonNullGraphType<HumanInputType>> {Name = "human"}
      ),
      resolve: context =>
      {
        var human = context.GetArgument<Human>("human");
        return data.AddHuman(human);
      });
  }
}

And that seems fine when you have 1-5 mutations, but overtime in some larger projects one could conceivably end up with dozens of mutations. Putting them in one big class together seems sufficient to work, although it also seems like there is some organization lacking. I tried putting a child mutation GraphTypeObject into a field on the parent mutation, but I had a little trouble calling the sub-mutation. Perhaps I had it configured wrong.

That just leads me to wonder, certainly there must be a user out there with more than a dozen mutations who might have organized their mutations beyond putting all their mutations in a single top level mutations object.

How does one organize more than a few mutations in GraphQL .Net GraphType First?


Solution

  • https://graphql-dotnet.github.io/docs/getting-started/query-organization

    You can "group" queries or mutations together by adding a top level field. The "trick" is to return an empty object in the resolver.

    public class StarWarsSchema : Schema
    {
      public StarWarsSchema(IServiceProvider provider)
        : base(provider)
      {
        Query = provider.Resolve<StarWarsQuery>();
        Mutation = provider.Resolve<StarWarsMutation>();
      }
    }
    
    public class StarWarsMutation : ObjectGraphType
    {
      public StarWarsMutation(StarWarsData data)
      {
        Field<CharacterMutation>(
          "characters",
          resolve: context => new { });
      }
    }
    
    public class CharacterMutation : ObjectGraphType
    {
      public CharacterMutation(StarWarsData data)
      {
        Field<HumanType>(
          "createHuman",
          arguments: new QueryArguments(
            new QueryArgument<NonNullGraphType<HumanInputType>> {Name = "human"}
          ),
          resolve: context =>
          {
            var human = context.GetArgument<Human>("human");
            return data.AddHuman(human);
          });
      }
    }
    

    This organization is reflected in how the mutations (or queries) are called. If you simply want them externally to appear as a flat list (which would equate to one giant file), you can also break it up into as many files as you want using partial classes.