Skip to content

GraphQL

Sann Lynn Htun edited this page Nov 22, 2024 · 2 revisions

0_Jlv_4jtIjpQXsRZ9

GraphQL

GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. It was developed by Facebook and released in 2015. It allows clients to request exactly the data they need, making it more efficient and powerful than traditional REST APIs.

Key Features:

  • Single Endpoint: GraphQL operates via a single endpoint.
  • Flexible Queries: Clients can request exactly the data they need.
  • Type System: Strongly-typed schema defines the data and operations available.
  • Real-time Data: Supports subscriptions for real-time updates.

Example Query:

{
  user(id: "1") {
    id
    name
    email
    posts {
      title
      comments {
        text
      }
    }
  }
}

Advantages:

  • Reduces over-fetching and under-fetching of data.
  • Provides a more predictable and self-documenting API.
  • Can combine multiple resources in a single request.

Summary

  • GraphQL offers a flexible and efficient way to interact with your data by allowing clients to specify exactly what they need. It reduces over-fetching and under-fetching, supports real-time data updates, and provides a strongly-typed schema for better predictability and self-documentation.

image

Step 1: Setting Up the ASP.NET Core Web API with HotChocolate

1. Create a new ASP.NET Core Web API project

dotnet new webapi -n GraphQLApi
cd GraphQLApi

2. Add necessary NuGet packages

dotnet add package HotChocolate.AspNetCore
dotnet add package HotChocolate.Data.EntityFramework
dotnet add package HotChocolate.Types
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

3. Define your DbContext and BlogModel

AppDbContext.cs

using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
    public DbSet<BlogModel> Blogs { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("YourConnectionStringHere");
    }
}

BlogModel.cs

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

[Table("Tbl_Blog")]
public class BlogModel
{
    [Key]
    public int Blog_Id { get; set; }
    public string Blog_Title { get; set; }
    public string Blog_Author { get; set; }
    public string Blog_Content { get; set; }
}

4. Define your GraphQL Queries and Mutations

BlogQuery.cs

using HotChocolate;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

public class BlogQuery
{
    public async Task<List<BlogModel>> Blogs([Service] AppDbContext db, int pageNo, int pageSize)
    {
        int skipRowCount = (pageNo - 1) * pageSize;
        return await db.Blogs.OrderByDescending(x => x.Blog_Id)
                             .Skip(skipRowCount)
                             .Take(pageSize).ToListAsync();
    }

    public async Task<BlogModel?> Blog([Service] AppDbContext db, int id)
    {
        return await db.Blogs.FirstOrDefaultAsync(x => x.Blog_Id == id);
    }
}

BlogMutation.cs

using HotChocolate;
using Microsoft.EntityFrameworkCore;
using System.Threading.Tasks;

public class BlogMutation
{
    public async Task<BlogModel> AddBlog([Service] AppDbContext db, BlogModel reqModel)
    {
        await db.Blogs.AddAsync(reqModel);
        await db.SaveChangesAsync();
        return reqModel;
    }

    public async Task<BlogModel> UpdateBlog([Service] AppDbContext db, int id, BlogModel reqModel)
    {
        reqModel.Blog_Id = id;
        db.Blogs.Update(reqModel);
        await db.SaveChangesAsync();
        return reqModel;
    }

    public async Task<BlogModel?> PatchBlog([Service] AppDbContext db, int id, BlogModel reqModel)
    {
        reqModel.Blog_Id = id;
        var item = await db.Blogs.FirstOrDefaultAsync(x => x.Blog_Id == id);
        if (item is null) return null;

        if (!string.IsNullOrEmpty(reqModel.Blog_Title))
            item.Blog_Title = reqModel.Blog_Title;
        if (!string.IsNullOrEmpty(reqModel.Blog_Author))
            item.Blog_Author = reqModel.Blog_Author;
        if (!string.IsNullOrEmpty(reqModel.Blog_Content))
            item.Blog_Content = reqModel.Blog_Content;

        db.Blogs.Update(item);
        await db.SaveChangesAsync();
        return item;
    }

    public async Task<int> DeleteBlog([Service] AppDbContext db, int id)
    {
        var item = await db.Blogs.FirstOrDefaultAsync(x => x.Blog_Id == id);
        if (item is null) return 0;

        db.Blogs.Remove(item);
        return await db.SaveChangesAsync();
    }
}

5. Configure HotChocolate in Program.cs or Startup.cs

Program.cs

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddDbContext<AppDbContext>();
builder.Services.AddGraphQLServer()
    .AddQueryType<BlogQuery>()
    .AddMutationType<BlogMutation>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

app.UseRouting();
app.UseEndpoints(endpoints =>
{
    endpoints.MapGraphQL();
});

app.Run();

Step 2: Setting Up StrawberryShake in Console App

1. Create a new Console App

dotnet new console -n GraphQLClient
cd GraphQLClient

2. Add StrawberryShake and System.Text.Json NuGet packages

dotnet add package StrawberryShake
dotnet add package System.Text.Json

3. Initialize StrawberryShake in your project

dotnet tool install -g StrawberryShake.Tools
dotnet new strawberryshake -n GraphQLClient

4. Update strawberryshake.json to configure your GraphQL endpoint

strawberryshake.json

{
  "SchemaName": "GraphQLClient",
  "ClientName": "GraphQLClient",
  "Namespace": "GraphQLClient",
  "Url": "https://localhost:5001/graphql"
}

5. Fetch the GraphQL schema and generate client code

dotnet graphql update

6. Use the generated client in your Console App

Program.cs

using System;
using System.Threading.Tasks;
using GraphQLClient;

class Program
{
    static async Task Main(string[] args)
    {
        var clientFactory = new GraphQLClientClientFactory();
        var client = clientFactory.Create();

        // Example Read
        var readResponse = await client.Blogs.ExecuteAsync(1, 10);
        if (readResponse.IsSuccessResult())
        {
            var blogs = readResponse.Data.Blogs;
            foreach (var blog in blogs)
            {
                Console.WriteLine($"Id: {blog.Blog_Id}, Title: {blog.Blog_Title}, Author: {blog.Blog_Author}");
            }
        }
        else
        {
            Console.WriteLine("Query failed");
        }

        // Example Create
        var createResponse = await client.AddBlog.ExecuteAsync(new BlogModelInput
        {
            Blog_Title = "New Blog",
            Blog_Author = "Author",
            Blog_Content = "Content"
        });
        if (createResponse.IsSuccessResult())
        {
            var createdBlog = createResponse.Data.AddBlog;
            Console.WriteLine($"Created Blog Id: {createdBlog.Blog_Id}");
        }
        else
        {
            Console.WriteLine("Mutation failed");
        }

        // Example Update
        var updateResponse = await client.UpdateBlog.ExecuteAsync(1, new BlogModelInput
        {
            Blog_Title = "Updated Blog",
            Blog_Author = "Updated Author",
            Blog_Content = "Updated Content"
        });
        if (updateResponse.IsSuccessResult())
        {
            var updatedBlog = updateResponse.Data.UpdateBlog;
            Console.WriteLine($"Updated Blog Id: {updatedBlog.Blog_Id}");
        }
        else
        {
            Console.WriteLine("Mutation failed");
        }

        // Example Delete
        var deleteResponse = await client.DeleteBlog.ExecuteAsync(1);
        if (deleteResponse.IsSuccessResult())
        {
            Console.WriteLine("Deleted Blog Id: 1");
        }
        else
        {
            Console.WriteLine("Mutation failed");
        }
    }
}

Summary

  1. Set up an ASP.NET Core Web API with HotChocolate for GraphQL server capabilities.
  2. Define a GraphQL schema with queries and mutations for CRUD operations.
  3. Set up a Console App using StrawberryShake to interact with the GraphQL API.
  4. Initialize, configure, and generate the GraphQL client code using StrawberryShake.
  5. Use the generated client in the Console App to perform GraphQL queries and mutations for CRUD operations.

C# Basics Wiki

Core Concepts

Object-Oriented Programming (OOP)

Advanced Topics

Miscellaneous

Tools and Resources

Clone this wiki locally