Schema basics

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.

SDL
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.

SDL
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.

C#
// Query.cs
public class Query
{
public Book GetBook() => new Book { Title = "C# in depth", Author = "Jon Skeet" };
}
// Book.cs
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
}
// Startup.cs
public 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.

SDL
type Query {
book(id: String): Book
}
type Book {
title: String
author: String
}
GraphQL
{
book(id: "abc") {
title
}
}
C#
// Query.cs
public class Query
{
public Task<Book> GetBookAsync(string id)
{
// Omitted code for brevity
}
}
// Book.cs
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
}
// Startup.cs
public 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.

SDL
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.

C#
// Query.cs
public class Query
{
// Omitted code for brevity
}
// Query.cs
public class Mutation
{
public async Task<Book> CreateBook(Book book)
{
}
}
// Book.cs
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
}
// Startup.cs
public 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.