...

by Paul Carson 03/22/2023

Set up an endpoint with GraphQL and Hot Chocolate

...

Introduction

For this project, I wanted to highlight some of the versatility of GraphQL using a publically available database. The use case I was envisioning is an existing database that needs to be exposed for different clients. GraphQL is a fantastic API technology providing the client with exactly what date it needs, reducing the amount of unnecessary data that is transferred over the network. This is in contrast to REST typically requires multiple requests to return data, resulting in slower and less efficient communication. It also has strongly typed schema so it's easy to understand and use. In addition, it provides an evolutionary design, so the API can evolve without breaking existing clients. This is because the client specifies what data it needs, and the server can add new fields and types to the schema without affecting existing clients. Overall, GraphQL is a more efficient, flexible, and developer-friendly alternative to REST.

Project Overview

I implemented a GraphQL API using .NET Core and the Hot Chocolate library to exposed the Wide World Importers database. This allows clients to query the data more efficiently by requesting only the data they need.

  • Database and Data Models:I used the existing Wide World Importers database schema, which involved several tables and relationships. I created the necessary data models and set up Entity Framework Core to interact with the database.
  • GraphQL Types:For each data model, defined a corresponding GraphQL Type. This allowed Hot Chocolate to understand the structure of the data and generate the appropriate GraphQL schema.
  • Schema and Query:Set up a GraphQL schema and a Query class to handle incoming GraphQL queries. The Query class included methods for fetching various entities and their related data
  • Middleware and Dependency Injection:Configured the Hot Chocolate GraphQL middleware in the Startup.cs file, along with the necessary services and repositories using dependency injection. This allowed us to keep our code modular and maintainable.
  • Technical Walkthrough

    1. Create a new ASP.NET Core Web Application project with an empty template.
    2. Install the necessary packages:
      
          HotChocolate.AspNetCore
          HotChocolate.AspNetCore.Playground
          HotChocolate.Data.EntityFramework
          Microsoft.EntityFrameworkCore
          Microsoft.EntityFrameworkCore.SqlServer
      
      
    3. Set up the database connection: In the appsettings.json, add the connection string for the Wide World Importers database.
      
              {
              "ConnectionStrings": {
              "WideWorldImporters": "YourConnectionStringHere"
              }
          }
      
    4. Scaffold the DbContext and entity classes using the dotnet ef dbcontext scaffold command
      
      dotnet ef dbcontext scaffold "Server=(local);Database=WideWorldImporters;User Id=myUsername;Password=myPassword;" Microsoft.EntityFrameworkCore.SqlServer -o Models
      
    5. Create a QueryType class for each entity you want to expose through the GraphQL API
      
      public class Query
          {
              [UseDbContext(typeof(WideWorldImportersDbContext))]
              public IQueryable GetCustomers([ScopedService] WideWorldImportersDbContext context)
              {
                  return context.Customers;
              }
              [UseDbContext(typeof(WideWorldImportersDbContext))]
              public IQueryable GetCustomerTransactions([ScopedService] WideWorldImportersDbContext context,
                  decimal amountGreaterThan)
              {
                  return context.CustomerTransactions
                      .Include(ct => ct.Customer)
                      .Where(ct => ct.TransactionAmount > amountGreaterThan);
              }
          }
      
      
    6. Configure the GraphQL schema by adding the Query and registering the QueryType classes in Program.cs
      
      
          // Configure the HTTP request pipeline.
          if (!app.Environment.IsDevelopment())
          {
              app.UseExceptionHandler("/Error");
      
              app.UseHsts();
          }
      
          app.UseHttpsRedirection();
          app.UseStaticFiles();
      
          app.UseRouting();
          app.MapGraphQL();
      
    7. Configure the GraphQL middleware in Program.cs
      
      
      var builder = WebApplication.CreateBuilder(args);
      
      // Add services to the container.
      builder.Services.AddDbContextFactory(options =>
      options.UseSqlServer(builder.Configuration.GetConnectionString("WideWorldImportersConnection")));
      
      
      builder.Services
      .AddRouting()
      .AddGraphQLServer()
      .AddQueryType()
      .AddType();
      
      builder.Services.AddScoped(sp => sp.GetRequiredService());
      

    Outcome and Conclusion

    To see what we get from all this, we can the Hot Chocolate UI: Banana Cake Pop. It exposes the schema and the data it can return. This is where the flexibility really shines. Let's walk through it

    • Here we can see the queries available and references to what we can do with them Wide World Importers Schema
    • A client or service may have a need for only some details about the customers (Marketing for example) so we can return just those items Wide World Importers Marketing
    • And another client may have a need for some additional detail around transactions over a certain dollar amount (Finance maybe) Wide World Importers Finance
    This benefits everyone. The developers need only add a new query and related items as need be versus having to write new endpoints. The clientss get their information more quickly and if (when) things break, it's in one location to be able to troubleshoot. It was a fun project to work and good to get into using GraphQL more. I hope you enjoyed the walk through.

    Contact Me for GraphQL, SQL, and Data Expertise