Перейти к основному содержимому

Доступ к данным из сервиса бизнес-логики

Для доступа к данным хранилища данных в состав Атомкод включены следующие клиентские библиотеки :

Библиотека ClientCore

Базовые настройки

Следующий блок кода демонстрирует регистрацию GraphQL-сервиса в контейнере зависимостей.

// Регистрация GraphQL-сервиса
services.AddGraphqlService<IGraphqlEndpoint>(config);

Следующий блок кода демонстрирует получение GraphQL-сервиса из контейнера зависимостей.

var service = _serviceProvider.GetService<IGraphQLService<IGraphqlEndpoint>>();

Следующий блок кода демонстрирует создание производного класса (на основе абстрактного класса GraphQLContext) для типизированного доступа к коллекциям сущностей.

public partial class SystemContext : GraphQLContext
{
public SystemContext(IGraphQLService service) : base(service)
{ }

/// <summary>
/// Доступ к сущностям 'File'
/// </summary>
public ILinqQueryContext<File, Guid> FileCollection => AsQueryable<File, Guid>();

/// <summary>
/// Доступ к сущностям 'Bucket'
/// </summary>
public ILinqQueryContext<Bucket, Guid> BucketCollection => AsQueryable<Bucket, Guid>();
}

Выполнение GraphQL-запросов

Следующий блок кода демонстрирует формирование и выполнение GraphQL-запроса.

// Формирование GraphQL-запроса
var graphqlQuery = @"query userOperation {
library_user {
items { email, login, name, id }
totalCount
}
}";

// Параметры запроса
var gqlParams = new GraphqlParams {
DiagTraceId = Guid.NewGuid(),
DiagTraceLevel = DiagTraceLevel.Debug
};

// Выполнение запроса
var service = _serviceProvider.GetService<IGraphQLService<IGraphqlEndpoint>>();
var result = await service.RequestAsync(graphqlQuery, gqlParams);

Следующий блок кода демонстрирует формирование и выполнение транзакции.

try
{
// Начало распределенной транзакции
context.BeginDistributedTransaction(
level: IsolationLevel.ReadCommitted,
timeoutMs: 60000);

// Операции над данными
// ...

// Фиксация изменений
context.CommitTransaction();
}
catch (Exception ex)
{
// Откат изменений при ошибке
context.RollBackTransaction();
}

Получение метаинформации о типах

Для получения метаинформации о существующих типах используется метод GetTypeInfo(). Этот метод возвращает информацию с единичным уровнем вложенности. Если необходимо получить информацию о полях вложенных объектных типов, рекомендуется формировать GraphQL-запрос вручную и использовать метод RequestAsync().

Следующий блок кода демонстрирует использование метода GetTypeInfo(). В качестве парамера метода используется имя типа в формате GraphQL: ({Имя_проекта}_{Имя_класса}).

TypeInfo typeInfo = context.GetTypeInfo("Library_authorbook");

Библиотека GraphQL

Генерация GraphQL-запросов

RequestBuilder — основной класс, который упрощает составление GraphQL-запросов.

Для генерации GraphQL-запросов используются цепочки вызовов методов. Каждая цепочка завершается методом ToGraphQL(), который формирует итоговый GraphQL-запрос.

Следующий блок кода демонстрирует формирование GraphQL-запроса с помощью класса RequestBuilder.

string graphqlQuery = RequestBuilder.From("system_file")
.Select("Id", "name", "bucket.Id", "bucket.name")
.OrderBy("name", OrderDirection.Asc)
.Where("deleted", ExpressionOperand.Equals, false)
.Where("name", ExpressionOperand.StartWith, "a")
.SkipTake(10, 20)
.ToGraphQL();

Следующий блок кода демонстрирует сформированный GraphQL-запрос.

query get_system_file {
system_file(
order: { name: ASC },
where: { and: [{ deleted: { eq: false } }, { name: { startsWith: "a" } }] },
take: 20,
skip: 10
) {
items {
Id,
name,
bucket {
Id,
name
}
}
}
}

Следующий блок кода демонстрирует формирование GraphQL-запроса без оператора Select.

string result = RequestBuilder.From("system_file")
.Where("deleted", ExpressionOperand.Equals, false)
.SkipTake(10, 20)
.AddPageInfo()
.AddTotalCount()

.ToGraphQL();

query get_system_file{system_file(where:{and:[{deleted:{eq:false}}]},take:20,skip:10){pageInfo{hasNextPage,hasPreviousPage},totalCount}}

Следующий блок кода демонстрирует сформированный GraphQL-запрос.

query get_system_file{
system_file(where: {and: [ {deleted: {eq:false} } ]}, take:20, skip:10)
{
pageInfo{
hasNextPage,
hasPreviousPage
},
totalCount
}
}

Вставка записей

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

// Одиночная вставка
string insertQuery = RequestBuilder.Insert("system_file") //"<имя проекта>_<имя класса>" в нижнем регистре
.Value("name", "aaa.txt") //1-й аргумент - название поля, 2-й аргумент - значение
.Value("bucket_id", "89976FEB-C184-43B0-9769-940F820B1D3F")
.ToGraphQL();

// Пакетная вставка
string bulkInsertQuery = RequestBuilder.BulkInsert("system_file")
.Entity([("name", "first.txt"), ("bucket_id", "58fa4244-3dd4-11ef-ad2b-02420a000ac5")])
.Entity([("name", "second.txt"), ("bucket_id", "58fa4244-3dd4-11ef-ad2b-02420a000ac5")])
.ToGraphQL();

Обновление записей

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

// Одиночное обновление
string updateQuery = RequestBuilder.Update("system_file")
.Where("Id", ExpressionOperand.Equals, "4600BD13-5A68-48C9-B573-612266AFAA2B")
.Value("name", "aaa.txt")
.ToGraphQL();

// Пакетное обновление двух записей
string bulkUpdateQuery = RequestBuilder.BulkUpdate("system_file")
.Entity([("Id", "c90f70b8-3dd4-11ef-ad2b-02420a000ac5"), ("deleted", true)])
.Entity([("Id", "c910260c-3dd4-11ef-ad2b-02420a000ac5"), ("deleted", true)])
.ToGraphQL();

Метод Entity() добавляет записи для обновления, где каждый кортеж представляет пару "поле-значение". Поле Id является обязательным.

Удаление записей

Следующий блок кода демонстрирует удаление записей.

string deleteQuery = RequestBuilder.Delete("system_file")
.Where("deleted", ExpressionOperand.Equals, false)
.ToGraphQL();

Вставка или обновление записей

Следующий блок кода демонстрирует операции вставки или обновления записей (Upsert).

// Одиночная вставка или обновление
string upsertExample = RequestBuilder.Upsert("system_file")
.Value("name", "aaa.txt")
.Value("bucket_id", "89976FEB-C184-43B0-9769-940F820B1D3F")
.ToGraphQL();

// Пакетная вставка или обновление двух записей
string bulkUpsertExample = RequestBuilder.BulkUpsert("system_file")
.Entity([("Id", "c90f70b8-3dd4-11ef-ad2b-02420a000ac5"), ("name", "aaa.txt"), ("bucket_id", "89976FEB-C184-43B0-9769-940F820B1D3F")])
.Entity([("Id", "c910260c-3dd4-11ef-ad2b-02420a000ac5"), ("deleted", true)])
.ToGraphQL();

Библиотека LinqToDto

Загрузка связанных сущностей

Следующий блок кода демонстрирует использование методов Include() и ThenInclude() для загрузки связанных сущностей.

var comments = context.CommentCollection
.Include(t => t.User)
.Include(t => t.Book)
.Include(t => t.Book.AuthorBookList)
.ThenInclude(t => t.Author)
.OrderBy(t => t.Title)
.Skip(1)
.Take(5)
.ToList();

Вставка записей

Следующий блок кода демонстрирует использование методов Insert() и BulkInsert() для одиночной и пакетной вставки.

var insertExample = context.BookCollection.Insert( new Book{ Name = "name1"});

var bulkInsertExample = context.BookCollection.BulkInsert(
new[]
{
new Book{ Name = "name1"},
new Book{ Name = "name2"},
new Book{ Name = "name3"},
new Book{ Name = "name4"},
new Book{ Name = "name5"}

});

Обновление записей

Следующий блок кода демонстрирует использование методов Update() и BulkUpdate() для одиночного и пакетного обновления.

// Одиночное обновление
var updatedCount = context.BookCollection
.Where(x => x.Id == bookId)
.Set(x => x.Name, "updated name")
.Update();

// Пакетное обновление
List<File> files = context.FileCollection.Skip(0).Take(3).ToList();
foreach (var file in files)
file.MaxVersion++;

var bulkResult = context.FileCollection.BulkUpdate(files);

Метод Set() указывает обновляемое поле и его новое значение.

Удаление записей

Следующий блок кода демонстрирует использование метода Delete() для удаления записей.

context.BookCollection
.Where(x => x.Id == bookId)
.Delete();

Вставка или обновление записей

Следующий блок кода демонстрирует использование методов Upsert() и BulkUpsert() для вставки или обновления записей с помощью операции Upsert.

// Одиночный Upsert
var upsertResult = context.BookCollection.Upsert(new Book { Name = "name5" });

// Пакетный Upsert
var bulkUpsertResult = context.BookCollection.BulkUpsert(booksToUpsert);