We are still working on the documentation for Hot Chocolate 11.1 so help us by finding typos, missing things or write some additional docs with us.
The schema in GraphQL represents the type system and exposes your business model in a strong and rich way. The schema fully describes the shape of your data and how you can interact with it.
Object Type
The most important type in a GraphQL schema is the object type which lets you consume data. Every object type has to have at least one field which holds the data of an object. Fields can return simple scalars like String, Int, or again object types.
type Book { title: String author: String}
Operations
In GraphQL, we have three root types from which only the Query type has to be defined. Root types provide the entry points that let you fetch data, mutate data, or subscribe to events. Root types themselves are object types.
Read more about GraphQL operation types here.
schema { query: Query}type Query { book: Book}type Book { title: String author: String}
In Hot Chocolate, there are three ways to define an object type.
Note: Every single code example will be shown in three different approaches, annotation-based (previously known as pure code-first), code-first, and schema-first. However, they will always result in the same outcome on a GraphQL schema perspective and internally in Hot Chocolate. All three approaches have their pros and cons and can be combined when needed with each other. If you would like to learn more about the three approaches in Hot Chocolate, click on Coding Approaches.
// Query.cspublic class Query{ public Book GetBook() => new Book { Title = "C# in depth", Author = "Jon Skeet" };}// Book.cspublic class Book{ public string Title { get; set; } public string Author { get; set; }}// Startup.cspublic class Startup{ public void ConfigureServices(IServiceCollection services) { services .AddRouting() .AddGraphQLServer() .AddQueryType<Query>(); } // Omitted code for brevity}
Fields
Fields of object types can be compared to methods in C# and allow us to pass in arguments.
type Query { book(id: String): Book}type Book { title: String author: String}
{ book(id: "abc") { title }}
// Query.cspublic class Query{ public Task<Book> GetBookAsync(string id) { // Omitted code for brevity }}// Book.cspublic class Book{ public string Title { get; set; } public string Author { get; set; }}// Startup.cspublic class Startup{ public void ConfigureServices(IServiceCollection services) { services .AddRouting() .AddGraphQLServer() .AddQueryType<Query>(); } // Omitted code for brevity}
Further reading:
Input Objects
In GraphQL we distinguish between input- and output-types. We already learned about object types which is the most prominent output-type and lets us consume data. Further, we used simple scalars like String
to pass data into a field as an argument. In order to define complex structures of raw data that can be used as input data GraphQL defines input objects.
input BookInput { title: String author: String}
If we wanted for instance to create a new book with a mutation we could do that like the following.
// Query.cspublic class Query{ // Omitted code for brevity}// Query.cspublic class Mutation{ public async Task<Book> CreateBook(Book book) { }}// Book.cspublic class Book{ public string Title { get; set; } public string Author { get; set; }}// Startup.cspublic class Startup{ public void ConfigureServices(IServiceCollection services) { services .AddRouting() .AddGraphQLServer() .AddQueryType<Query>() .AddMutationType<Mutation>(); } // Omitted code for brevity}
Lists
Nullability
GraphQL has a concept of nun-null types. Basically any type can be a non-nullable type, in the SDL we decorate non-nullable types with the Bang
token !
. In order to describe this in C# we can use attributes, use C# nullable reference types or use the underlying schema types to describe our GraphQL type explicitly.