How can you split the Query / Mutation / Subscription type into multiple files with HotChocolate GraphQL?
Asked Answered
I

2

5

I'm the new guy in the GraphQL world and trying to find a way to have multiple Query types or how to split the Query type into multiple files.. I use Hot Chocolate for Asp.Net Core, and everything looks good and works. But what if I need to combine few queries in one GraphQL API? Some really unrelated stuff, f.e. DogsQuery and CarsQuery.

In Asp.Net, I write similar to:

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddGraphQLServer()
            //.AddQueryType<DogsQuery>()
            .AddQueryType<CarsQuery>();
}

It works fine if I use only one Query class simultaneously (Dogs or Cars). But how to use both? I've searched a lot but can't find the answer.

Ironworks answered 29/1, 2021 at 10:32 Comment(0)
B
10

You cannot have multiple Query/Mutation/Subscription types in graphql, but you can split the types to multiple files in HotChocolate.

You can use the [ExtendObjectType(Name = "Query")] attribute above both your query types. This works for the Subscriptions ([ExtendObjectType(Name = "Subscription")]) and Mutations ([ExtendObjectType(Name = "Mutation")]) the same way.

This attribute is used for merging any two graphql types in the same HotChocolate server. The name value must be the name of the GraphQl type you want to merge your C# class into. In this case it is Query.

After doing that, you can add the types to your server like this:

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddGraphQLServer()
            .AddQueryType(d => d.Name("Query"))
                .AddTypeExtension<DogsQuery>()
                .AddTypeExtension<CarsQuery>();
}

You can find this and many more useful things in the workshop example on Github: https://github.com/ChilliCream/graphql-workshop

Bartolemo answered 31/1, 2021 at 16:2 Comment(1)
Thanks a lot. I've started to use partial classes for that (at least to separate physical files for Dogs and Cars), but this approach is much elegant.Ironworks
C
1

I created an extension class for IRequestExecutorBuilder that allows me to build queries and mutations fore each entity classes, inheriting from EntityQuery and EntityMutation and not have to worry about adding each type extensions.

public static class IRequestExecutorBuilderExtensions
{
    public static void AddGraphQLTypes(this IRequestExecutorBuilder requestExecutorBuilder)
    {
        requestExecutorBuilder
            .AddMutationType(d => d.Name("Mutation"))
            .AddQueryType(d => d.Name("Query"));

        var mutations = typeof(EntityMutation).GetAllSubTypes().ToList();
        mutations.ForEach(t => requestExecutorBuilder.AddTypeExtension(t));

        var queries = typeof(EntityQuery).GetAllSubTypes().ToList();
        queries.ForEach(t => requestExecutorBuilder.AddTypeExtension(t));
    }
}

which can be called within Program.cs

builder.Services
    .AddGraphQLServer()
    .AddProjections()
    .RegisterDbContext<MyDbContext>(DbContextKind.Pooled)
    .AddErrorFilter(e =>
    {
        Console.WriteLine(e);
        return e;
    })
    .AddGraphQLTypes();

This also relies on another TypeExtension class that I use often

public static class TypeExtensions
{
    public static IEnumerable<Type> GetAllSubTypes(this Type type)
    {
        var allTypes = type.Assembly.GetTypes();

        var types = from x in allTypes
                    where x.BaseType != null && x.BaseType.Name == type.Name
                    select x;

        return types;
    }
}
Coverup answered 4/7, 2024 at 17:20 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.