Введение
В этой статье мы поговорим о пагинации на GraphQL.
-
Если вы не знаете, что такое graphQL, пожалуйста, ознакомьтесь с нашей статьей.
-
О конфигурировании и первоначальном использовании graphQL читайте в этой статье.
Одним из наиболее эффективных способов работы с GraphQL является взаимодействие при помощи интерфейса IQueryable. Наш второй проект в репозитории (002_GraphQLWithEFCore) посвящен обеспечению взаимодействия GraphQL с EF Core (Entity Framework (EF) Core — это простая, кроссплатформенная и расширяемая версия популярной технологии доступа к данным Entity Framework с открытым исходным кодом).
Сначала давайте введем данные о Customer (клиент) и Card (карта) в базу данных с помощью EF Core.
public class Customer { public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } public List<Card> Cards { get; set; } } public class Card { public int Id { get; set; } public string Number { get; set; } public string CVC { get; set; } public string ExpiryDate { get; set; } public int CustomerId { get; set; } public Customer Customer { get; set; } }
Давайте настроим DbContext:
public class GraphQLAppDbContext : DbContext { public GraphQLAppDbContext(DbContextOptions<GraphQLAppDbContext> options) : base(options) { } public DbSet<Customer> Customers { get; set; } public DbSet<Card> Cards { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Customer>() .HasMany(e => e.Cards) .WithOne(x => x.Customer) .HasForeignKey(x => x.CustomerId) .IsRequired(); modelBuilder.Entity<Customer>() .HasData(new Customer() { Id = 1, Email = "id1@gmail.com", Name = "Simon Baker" }, new Customer() { Id = 2, Email = "id2@gmail.com", Name = "Hanayama Kaoru" }, new Customer() { Id = 3, Email = "id3@gmail.com", Name = "Hanma Baki" }, new Customer() { Id = 4, Email = "id4@gmail.com", Name = "O. Doppo" }); modelBuilder.Entity<Card>() .HasData(new Card() { Id = 1, CustomerId = 1, Number = "1234-2345-3445-3456", CVC = "345", ExpiryDate = "08/26" }, new Card() { Id = 2, CustomerId = 2, Number = "1234-2345-3445-3456", CVC = "345", ExpiryDate = "08/26" }, new Card() { Id = 3, CustomerId = 3, Number = "3344-7654-3445-3456", CVC = "123", ExpiryDate = "09/25" }, new Card() { Id = 4, CustomerId = 4, Number = "5566-5454-3445-3456", CVC = "234", ExpiryDate = "07/24" }, new Card() { Id = 5, CustomerId = 1, Number = "6677-3232-3445-3456", CVC = "987", ExpiryDate = "06/26" }, new Card() { Id = 6, CustomerId = 1, Number = "8899-9898-3445-3456", CVC = "654", ExpiryDate = "05/27" }, new Card() { Id = 7, CustomerId = 2, Number = "9900-5678-3445-3456", CVC = "432", ExpiryDate = "04/28" }, new Card() { Id = 8, CustomerId = 1, Number = "1122-5678-3445-3456", CVC = "165", ExpiryDate = "03/23" }, new Card() { Id = 9, CustomerId = 2, Number = "2233-2543-3445-3456", CVC = "651", ExpiryDate = "02/29" }, new Card() { Id = 10, CustomerId = 3, Number = "3544-1234-3445-3456", CVC = "987", ExpiryDate = "01/26" }); base.OnModelCreating(modelBuilder); } }
Далее давайте настроим наш Query resolver (распознаватель запросов). (код)
public class Query { public IQueryable<Customer> GetCustomers([Service] GraphQLAppDbContext graphqldbcontext) => graphqldbcontext.Customers.Include("Cards"); }
Наконец, давайте настроим hotchocolate, как в первом проекте.
using _002_GraphQLWithEFCore.Database; using _002_GraphQLWithEFCore.Queries; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<GraphQLAppDbContext>( options => options.UseSqlServer("Data Source=.;Initial Catalog=GraphQLDb;Integrated Security=SSPI;TrustServerCertificate=True;")); builder.Services.AddGraphQLServer() .AddQueryType<Query>(); var app = builder.Build(); app.MapGraphQL(); app.Run();
Теперь, когда мы готовы запустить наш проект, можно получить всю информацию о клиенте и его карте в следующей форме.

Пагинация в GraphQL
Пагинация — это один из основных механизмов, который мы постоянно применяем на практике, и он позволяет получать данные по частям, а не целиком.
Используемые в настоящее время формы пагинации делятся на 2 вида:
Пагинация на основе смещения
Это форма пагинации с комбинацией Skip-Take, которую мы также часто используем в EF Core. Но в системах с большим потоком данных такая форма пагинации не очень удобна. Представьте, что вы получаете топ-10 данных в системе с огромным потоком информации; в систему добавляется все больше данных, следующие же 10 данных будут начальными 10-ю данными, которые вы уже получали. (мы не привязаны к элементам).

Допустим, skip(3).Take(3) вернет элементы [ 8, 7, 6 ], если нет уникального идентификатора сортировки. Но в следующий раз (сценарий 2), если при вызове пагинации информация уже была введена, мы снова получим те же данные, используя Skip(3).Take(3). ( [ 9, 8, 7] )
Пагинация на основе курсора
В отличие от пагинации на основе смещения, поскольку эта форма пагинации зависит от конкретных атрибутов сущности (в большинстве случаев от id), она всегда предоставляет уникальную информацию и по умолчанию перемещается вперед. В этом случае мы решаем вышеуказанную проблему, формируя команду типа "give 5 elements after id=7" (предоставить 5 элементов после id=7).
GrahpQL использует пагинацию на основе курсора. Настроить пагинацию с помощью библиотеки hot chocolate очень просто. Вам просто нужно добавить декоратор [UsePaging] в функции/резольверы запроса.
public class Query { [UsePaging(MaxPageSize = 2)] public IQueryable<Customer> GetCustomers([Service] GraphQLAppDbContext graphqldbcontext) => graphqldbcontext.Customers.Include("Cards"); }
По умолчанию graphQL возвращает на страницу 10 элементов. Однако это можно изменить с помощью параметра MaxPagesize. Если снова посмотреть на схему graphQL после добавления атрибута UsePaging, мы увидим в ней некоторые изменения.

Чтобы получить доступ к конфигурации пагинации, в интерфейс добавляется элемент pageInfo, а к элементам сущностей мы можем обращаться через nodes (узлы).

Чтобы получить следующий элемент, нам нужно использовать индекс курсора, определенный как endcursor, и указать, какое количество элементов мы хотим получить дальше.

Материал подготовлен в преддверии старта курса «C# Developer. Professional».
ссылка на оригинал статьи https://habr.com/ru/articles/749272/
Добавить комментарий