В этой статье мы обсудим основы GraphQL и один пример использования .NET Core Web API.

Повестка дня

  • Введение
  • Пример
  • Функции
  • Базовые концепты
  • Реализация с использованием .NET Core 7 API

Предпосылки

  • Визуальная студия 2022
  • Пакет SDK для .NET Core 7

Введение

  • GraphQL — это серверная технология с открытым исходным кодом, разработанная Facebook для оптимизации вызовов RESTful API.
  • GraphQL — это язык запросов для API и среда выполнения на стороне сервера для выполнения запросов и сбора данных из разных источников.
  • Используя GraphQL, мы можем извлекать данные из того, что нам нужно, только с помощью одной конечной точки.

  • GraphQL строго типизирован, поэтому мы можем проверить наш запрос в GraphQL перед выполнением, что помогает нам создавать более надежные API.
  • GraphQL быстрый, стабильный и всегда дает нам предсказуемые результаты.
  • Если вы хотите узнать больше о GraphQL, посетите официальный сайт GraphQL.

Пример

  • Предположим, у нас есть одна служба приложений продукта, и она будет возвращать сведения о продукте, такие как идентификатор, название продукта, описание продукта, цена продукта и запас продукта.
  • Но один из пользователей хочет получить название продукта и сведения о запасах, и для этого у него есть конечная точка API, такая как https://localhost:5000/api/v1/getproductdetails, он вернет все остальные поля с избыточной выборкой. Итак, эту проблему мы можем решить с помощью GraphQL, как показано ниже.
query{
  productList {
    id,
    productName,
    productStock
  }
}

Функции

  • GraphQL работает с другой базой данных.
  • Удобочитаемый синтаксис.
  • Использование GraphQL не решает проблем с получением данных.
  • Извлекайте данные с помощью одного вызова API.

Основные понятия

GraphQL имеет следующие компоненты, и каждый из них имеет свое назначение.

  1. Запрос — запрос — это запрос API, отправленный клиентом, который мы использовали для получения значений, и он имеет поля и аргументы, с помощью которых мы можем получать данные в соответствии с требованиями.
  2. Схема — схема используется для формирования наших доступных данных, и GraphQL имеет язык определения схемы (SDL) для написания схемы.
  3. Типы. Типы — это самая важная функция GraphQL, которая помогает нам создавать настраиваемые объекты и использовать их для извлечения данных.
  4. Мутация. Мутация используется для операции, отправляемой на сервер для создания, обновления и удаления данных.

Чтобы узнать больше о типах, запросах и схемах, посетите официальный сайт GraphQL.

Реализация с использованием .NET Core 7 API

В этой статье мы используем Hot Chocolate для GraphQL.

Горячий шоколад

  • Hot Chocolate — это сервер GraphQL с открытым исходным кодом для платформы Microsoft .NET.
  • Это снижает сложность и фокусируется на быстрой доставке вещей.
  • Горячий шоколад совместим со всеми клиентами, такими как Apollo Client, Relay и многими другими.

Шаг 1

Откройте визуальную студию и создайте новый веб-API .NET Core.

Шаг 2

Установите следующие пакеты NuGet.

Шаг 3

Создайте класс сведений о продукте.

namespace graphql_demo.Entities
{
    public class ProductDetails
    {
        public Guid Id { get; set; }
        public string ProductName { get; set; }
        public string ProductDescription { get; set; }
        public int ProductPrice { get; set; }
        public int ProductStock { get; set; }
    }
}

Шаг 4

Затем добавьте DbContextClass в папку данных.

using graphql_demo.Entities;
using Microsoft.EntityFrameworkCore;

namespace graphql_demo.Data
{
    public class DbContextClass : DbContext
    {
        public DbContextClass(DbContextOptions<DbContextClass>
options) : base(options)
        {
        }
        public DbSet<ProductDetails> Products { get; set; }
    }
}

Шаг 5

Добавьте класс начальных данных внутри данных, который помогает добавить некоторые записи изначально, когда мы запускаем приложение.

using graphql_demo.Entities;
using Microsoft.EntityFrameworkCore;

namespace graphql_demo.Data
{
    public class SeedData
    {
        public static void Initialize(IServiceProvider serviceProvider)
        {
            using (var context = new DbContextClass(
                serviceProvider.GetRequiredService<DbContextOptions<DbContextClass>>()))
            {
                if (context.Products.Any())
                {
                    return;
                }
                context.Products.AddRange(
                    new ProductDetails
                    {
                        Id = Guid.NewGuid(),
                        ProductName = "IPhone",
                        ProductDescription = "IPhone 14",
                        ProductPrice = 120000,
                        ProductStock = 100
                    },
                    new ProductDetails
                    {
                        Id = Guid.NewGuid(),
                        ProductName = "Samsung TV",
                        ProductDescription = "Smart TV",
                        ProductPrice = 400000,
                        ProductStock = 120
                    });
                context.SaveChanges();
            }
        }
    }
}

Шаг 6

Создайте IProductService и ProductService в папке репозиториев.

IPProductService

using graphql_demo.Entities;

namespace graphql_demo.Repositories
{
    public interface IProductService
    {
        public Task<List<ProductDetails>> ProductListAsync();
        public Task<ProductDetails> GetProductDetailByIdAsync(Guid productId);
        public Task<bool> AddProductAsync(ProductDetails productDetails);
        public Task<bool> UpdateProductAsync(ProductDetails productDetails);
        public Task<bool> DeleteProductAsync(Guid productId);
    }
}

ПродуктСервис

using graphql_demo.Data;
using graphql_demo.Entities;
using Microsoft.EntityFrameworkCore;

namespace graphql_demo.Repositories
{
    public class ProductService : IProductService
    {
        private readonly DbContextClass dbContextClass;
        public ProductService(DbContextClass dbContextClass)
        {
            this.dbContextClass = dbContextClass;
        }
        public async Task<List<ProductDetails>> ProductListAsync()
        {
            return await dbContextClass.Products.ToListAsync();
        }
        public async Task<ProductDetails> GetProductDetailByIdAsync(Guid productId)
        {
            return await dbContextClass.Products.Where(ele => ele.Id == productId).FirstOrDefaultAsync();
        }
        public async Task<bool> AddProductAsync(ProductDetails productDetails)
        {
            await dbContextClass.Products.AddAsync(productDetails);
            var result = await dbContextClass.SaveChangesAsync();
            if (result > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public async Task<bool> UpdateProductAsync(ProductDetails productDetails)
        {
            var isProduct = ProductDetailsExists(productDetails.Id);
            if (isProduct)
            {
                dbContextClass.Products.Update(productDetails);
                var result = await dbContextClass.SaveChangesAsync();
                if (result > 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            return false;
        }
        public async Task<bool> DeleteProductAsync(Guid productId)
        {
            var findProductData = dbContextClass.Products.Where(_ => _.Id == productId).FirstOrDefault();
            if (findProductData != null)
            {
                dbContextClass.Products.Remove(findProductData);
                var result = await dbContextClass.SaveChangesAsync();
                if (result > 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            return false;
        }
        private bool ProductDetailsExists(Guid productId)
        {
            return dbContextClass.Products.Any(e => e.Id == productId);
        }
    }
}

Шаг 7

Добавьте новую папку GraphQL для запросов и типов мутаций.

Шаг 8

Затем добавьте ProductQueryTypes в папку типов запросов, которая поможет нам получить данные о продукте.

using graphql_demo.Entities;
using graphql_demo.Repositories;

namespace graphql_demo.GraphQL.Types
{
    public class ProductQueryTypes
    {
        public async Task<List<ProductDetails>> GetProductListAsync([Service] IProductService productService)
        {
            return await productService.ProductListAsync();
        }
        public async Task<ProductDetails> GetProductDetailsByIdAsync([Service] IProductService productService, Guid productId)
        {
            return await productService.GetProductDetailByIdAsync(productId);
        }
    }
}

Шаг 9

Создайте папку типов мутаций и добавьте в нее класс ProductMutations, который поможет нам добавлять, обновлять и удалять данные о продукте.

using graphql_demo.Entities;
using graphql_demo.Repositories;

namespace graphql_demo.GraphQL.Mutations
{
    public class ProductMutations
    {
        public async Task<bool> AddProductAsync([Service] IProductService productService,
    ProductDetails productDetails)
        {
            return await productService.AddProductAsync(productDetails);
        }
        public async Task<bool> UpdateProductAsync([Service] IProductService productService,
    ProductDetails productDetails)
        {
            return await productService.UpdateProductAsync(productDetails);
        }
        public async Task<bool> DeleteProductAsync([Service] IProductService productService,
   Guid productId)
        {
            return await productService.DeleteProductAsync(productId);
        }
    }
}

Шаг 10

Зарегистрируйте несколько сервисов и промежуточного ПО внутри класса Program, связанных с репозиторием, начальными данными, запросом и типом мутации и многим другим.

using graphql_demo.Data;
using graphql_demo.GraphQL.Mutations;
using graphql_demo.GraphQL.Types;
using graphql_demo.Repositories;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);
//Register Service
builder.Services.AddScoped<IProductService, ProductService>();
//InMemory Database
builder.Services.AddDbContext<DbContextClass>
(o => o.UseInMemoryDatabase("GraphQLDemo"));
//GraphQL Config
builder.Services.AddGraphQLServer()
    .AddQueryType<ProductQueryTypes>()
    .AddMutationType<ProductMutations>();
var app = builder.Build();
//Seed Data
using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    var context = services.GetRequiredService<DbContextClass>();
    SeedData.Initialize(services);
}
//GraphQL
app.MapGraphQL();
app.UseHttpsRedirection();
app.Run();

Шаг 11

Запустить приложение

  • Получить список продуктов

  • Добавить сведения о продукте

  • Обновить сведения о продукте

  • Удалить сведения о продукте

  • Получить информацию о продукте по идентификатору

Ссылка на GitHub

https://github.com/Jaydeep-007/graphql_demo

Заключение

Здесь мы обсудили основы GraphQL, функции и пошаговую реализацию с использованием .NET Core Web API.

Удачного программирования!!!