Приложение на C# (.NET)
На этой странице подробно разбирается код тестового приложения, использующего C# (.NET) SDK YDB.
Примечание
Материал статьи дополняется.
Инициализация соединения с базой данных
Для взаимодействия с YDB создается экземпляр драйвера, клиента и сессии:
- Драйвер YDB отвечает за взаимодействие приложения и YDB на транспортном уровне. Драйвер должен существовать на всем протяжении жизненного цикла работы с YDB и должен быть инициализирован перед созданием клиента и сессии.
- Клиент YDB работает поверх драйвера YDB и отвечает за работу с сущностями и транзакциями.
- Сессия YDB содержит информацию о выполняемых транзакциях и подготовленных запросах и содержится в контексте клиента YDB.
Фрагмент кода приложения для инициализации драйвера:
public static async Task Run(
string endpoint,
string database,
ICredentialsProvider credentialsProvider)
{
var config = new DriverConfig(
endpoint: endpoint,
database: database,
credentials: credentialsProvider
);
using var driver = new Driver(
config: config
);
await driver.Initialize();
}
Фрагмент кода приложения для создания сессии:
using var tableClient = new TableClient(driver, new TableClientConfig());
Создание таблиц
Выполняется создание таблиц, которые используются в дальнейших операциях тестового приложения. В результате исполнения шага в базе данных будут созданы таблицы модели данных справочника сериалов:
series
- Сериалыseasons
- Сезоныepisodes
- Эпизоды
После создания вызывается метод получения информации об объекте схемы данных, и выводится результат его выполнения.
Для создания таблиц используется метод session.ExecuteSchemeQuery
с DDL (Data Definition Language) YQL-запросом.
var response = await tableClient.SessionExec(async session =>
{
return await session.ExecuteSchemeQuery(@"
CREATE TABLE series (
series_id Uint64 NOT NULL,
title Utf8,
series_info Utf8,
release_date Date,
PRIMARY KEY (series_id)
);
CREATE TABLE seasons (
series_id Uint64,
season_id Uint64,
title Utf8,
first_aired Date,
last_aired Date,
PRIMARY KEY (series_id, season_id)
);
CREATE TABLE episodes (
series_id Uint64,
season_id Uint64,
episode_id Uint64,
title Utf8,
air_date Date,
PRIMARY KEY (series_id, season_id, episode_id)
);
");
});
response.Status.EnsureSuccess();
Запись данных
Выполняется запись данных в созданные таблицы с использованием команды UPSERT
языка запросов YQL. Применяется режим передачи запроса на изменение данных с автоматическим подтверждением транзакции в одном запросе к серверу.
Фрагмент кода, демонстрирующий выполнение запроса на запись/изменение данных:
var response = await tableClient.SessionExec(async session =>
{
var query = @"
DECLARE $id AS Uint64;
DECLARE $title AS Utf8;
DECLARE $release_date AS Date;
UPSERT INTO series (series_id, title, release_date) VALUES
($id, $title, $release_date);
";
return await session.ExecuteDataQuery(
query: query,
txControl: TxControl.BeginSerializableRW().Commit(),
parameters: new Dictionary<string, YdbValue>
{
{ "$id", YdbValue.MakeUint64(1) },
{ "$title", YdbValue.MakeUtf8("NewTitle") },
{ "$release_date", YdbValue.MakeDate(DateTime.UtcNow) }
}
);
});
response.Status.EnsureSuccess();
PRAGMA TablePathPrefix
добавляет указанный префикс к путям таблиц внутри БД. Работает по принципу объединения путей в файловой системе — поддерживает ссылки на родительский каталог и не требует добавления слеша справа. Например:
PRAGMA TablePathPrefix = "/cluster/database";
SELECT * FROM episodes;
Подробнее о PRAGMA YQL можно прочитать в документации YQL.
Получение выборки данных
Выполняется запрос на получение выборки данных с использованием команды SELECT
языка запросов YQL. Демонстрируется обработка полученной выборки в приложении.
Для выполнения YQL-запросов используется метод session.ExecuteDataQuery()
. SDK позволяет в явном виде контролировать выполнение транзакций и настраивать необходимый режим выполнения транзакций с помощью класса TxControl
. В фрагменте кода, приведенном ниже, используется транзакция с режимом SerializableRW
и автоматическим коммитом после выполнения запроса. Значения параметров запроса передаются в виде словаря имя-значение в аргументе parameters
.
var response = await tableClient.SessionExec(async session =>
{
var query = @"
DECLARE $id AS Uint64;
SELECT
series_id,
title,
release_date
FROM series
WHERE series_id = $id;
";
return await session.ExecuteDataQuery(
query: query,
txControl: TxControl.BeginSerializableRW().Commit(),
parameters: new Dictionary<string, YdbValue>
{
{ "$id", YdbValue.MakeUint64(id) }
},
);
});
response.Status.EnsureSuccess();
var queryResponse = (ExecuteDataQueryResponse)response;
var resultSet = queryResponse.Result.ResultSets[0];
Обработка результатов выполнения
Результат выполнения запроса (ResultSet) состоит из упорядоченного набора строк (Rows). Пример обработки результата выполнения запроса:
foreach (var row in resultSet.Rows)
{
Console.WriteLine($"> Series, " +
$"series_id: {(ulong)row["series_id"]}, " +
$"title: {(string?)row["title"]}, " +
$"release_date: {(DateTime?)row["release_date"]}");
}
Скан запросы
Выполняется скан запрос данных, результатом исполнения которого является стрим. Стрим позволяет считать неограниченное количество строк и объем данных.
public void executeScanQuery()
{
var scanStream = TableClient.ExecuteScanQuery(@$"
SELECT series_id, season_id, COUNT(*) AS episodes_count
FROM episodes
GROUP BY series_id, season_id
ORDER BY series_id, season_id;
");
while (await scanStream.Next())
{
scanStream.Response.EnsureSuccess();
var resultSet = scanStream.Response.Result.ResultSetPart;
if (resultSet != null)
{
foreach (var row in resultSet.Rows)
{
Console.WriteLine($"> ScanQuery, " +
$"series_id: {(ulong)row["series_id"]}, " +
$"season_id: {(ulong?)row["season_id"]}, " +
$"episodes_count: {(ulong)row["episodes_count"]}");
}
}
}
}