Руководство. Разработка консольного приложения .NET с помощью Azure Cosmos DB для NoSQL
ОБЛАСТЬ ПРИМЕНЕНИЯ: NoSQL
Пакет SDK Azure для .NET позволяет добавлять данные в контейнер API для NoSQL либо асинхронные отдельные операции, либо пакет транзакций. В этом руководстве описывается процесс создания консольного приложения .NET, которое добавляет несколько элементов в контейнер.
В этом руководстве описано следующее:
- Создание базы данных с помощью API для NoSQL
- Создание консольного приложения .NET и добавление пакета SDK Azure для .NET
- Добавление отдельных элементов в контейнер API для NoSQL
- Извлечение элементов из контейнера API для NoSQL
- Создание транзакции с пакетными изменениями для контейнера API для NoSQL
Необходимые компоненты
- Существующая учетная запись Azure Cosmos DB для NoSQL.
- Если у вас есть подписка Azure, создайте новую учетную запись.
- Нет подписки Azure? Вы можете попробовать Azure Cosmos DB бесплатно без кредитной карты.
- Visual Studio Code
- .NET 8 или более поздней версии
- Опыт написания приложений C#.
Создание ресурсов API для NoSQL
Сначала создайте пустую базу данных в существующей учетной записи API для NoSQL. Вы создадите контейнер с помощью пакета SDK Azure для .NET позже.
Перейдите к существующей учетной записи API для NoSQL в портал Azure.
В меню ресурсов выберите "Ключи".
На странице "Ключи" просмотрите и запишите значение полей URI и PRIMARY KEY. Эти значения используются во всем руководстве.
В меню ресурсов выберите Обозреватель данных.
На странице обозревателя данных выберите параметр "Создать базу данных" на панели команд.
В диалоговом окне "Новая база данных" создайте контейнер со следующими параметрами:
Значение Идентификатор базы данных cosmicworks
Тип пропускной способности базы данных Вручную Объем пропускной способности базы данных 400
Нажмите кнопку "ОК ", чтобы создать базу данных.
Создание консольного приложения .NET
Теперь вы создадите консольное приложение .NET и импортируете пакет SDK Azure для .NET с помощью библиотеки Microsoft.Azure.Cosmos
из NuGet.
Откройте терминал в пустом каталоге.
Создание консольного приложения с помощью встроенного
console
шаблонаdotnet new console --langVersion preview
Добавьте версию
Microsoft.Azure.Cosmos
пакета 3.31.1-preview из NuGet.dotnet add package Microsoft.Azure.Cosmos --version 3.31.1-preview
Кроме того, добавьте предварительную версию
System.CommandLine
пакета из NuGet.dotnet add package System.CommandLine --prerelease
Кроме того, добавьте
Humanizer
пакет из NuGet.dotnet add package Humanizer
Создайте проект консольного приложения.
dotnet build
Откройте Visual Studio Code, используя текущую папку проекта в качестве рабочей области.
Совет
Вы можете запустить
code .
терминал, чтобы открыть Visual Studio Code и автоматически открыть рабочий каталог в качестве текущей рабочей области.Перейдите к файлу Program.cs и откройте его. Удалите весь существующий код в файле.
Добавьте этот код в файл, чтобы использовать библиотеку System.CommandLine для синтаксического анализа командной строки для двух строк, передаваемых через
--first
параметры и--last
параметры.using System.CommandLine; var command = new RootCommand(); var nameOption = new Option<string>("--name") { IsRequired = true }; var emailOption = new Option<string>("--email"); var stateOption = new Option<string>("--state") { IsRequired = true }; var countryOption = new Option<string>("--country") { IsRequired = true }; command.AddOption(nameOption); command.AddOption(emailOption); command.AddOption(stateOption); command.AddOption(countryOption); command.SetHandler( handle: CosmosHandler.ManageCustomerAsync, nameOption, emailOption, stateOption, countryOption ); await command.InvokeAsync(args);
Примечание.
В этом руководстве не совсем важно понимать, как работает средство синтаксического анализа командной строки. Средство синтаксического анализа имеет четыре параметра, которые можно указать при запуске приложения. Три из этих параметров являются обязательными, так как они будут использоваться для создания полей идентификатора и ключа секции.
На этом этапе проект не будет строиться, так как вы еще не определили статический
CosmosHandler.ManageCustomerAsync
метод.Сохраните файл Program.cs.
Добавление элементов в контейнер с помощью пакета SDK
Затем вы используете отдельные операции для добавления элементов в контейнер API для NoSQL. В этом разделе описано CosmosHandler.ManageCustomerAsync
, как определить метод.
Создайте файл CosmosHandler.cs .
В файле CosmosHandler.cs добавьте новую директиву using для
Humanizer
пространств имен иMicrosoft.Azure.Cosmos
пространств имен.using Humanizer; using Microsoft.Azure.Cosmos;
Создайте новый статический класс с именем
CosmosHandler
.public static class CosmosHandler { }
Чтобы проверить работу этого приложения, создайте короткую реализацию статического
ManageCustomerAsync
метода для печати входных данных командной строки.public static async Task ManageCustomerAsync(string name, string email, string state, string country) { await Console.Out.WriteLineAsync($"Hello {name} of {state}, {country}!"); }
Сохраните файл CosmosHandler.cs .
Вернитесь в терминал, запустите приложение.
dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
Выходные данные команды должны быть веселым приветствием.
Hello Mica Pereira of Washington, United States!
Вернитесь к файлу CosmosHandler.cs .
В статическом классе CosmosHandler добавьте новый
private static readonly
член типаCosmosClient
с именем_client
.private static readonly CosmosClient _client;
Создайте статический конструктор для
CosmosHandler
класса.static CosmosHandler() { }
В конструкторе создайте новый экземпляр
CosmosClient
класса, передавая два строковых параметра со значениями URI и PRIMARY KEY , записанными ранее в лаборатории. Сохраните этот новый экземпляр в члене_client
.static CosmosHandler() { _client = new CosmosClient( accountEndpoint: "<uri>", authKeyOrResourceToken: "<primary-key>" ); }
Вернитесь в статический класс CosmosHandler , создайте новый асинхронный метод с именем
GetContainerAsync
, возвращающим объектContainer
.private static async Task<Container> GetContainerAsync() { }
Чтобы выполнить следующие действия, добавьте этот код в
GetContainerAsync
метод.Получите базу данных и сохраните
cosmicworks
ее в переменной с именемdatabase
.Database database = _client.GetDatabase("cosmicworks");
Создайте новый универсальный набор
List<>
string
значений в списке путей иерархического ключа секции и сохраните его в переменной с именемkeyPaths
.List<string> keyPaths = new() { "/address/country", "/address/state" };
Создайте новую
ContainerProperties
переменную с именем контейнера (customers
) и списком путей ключа секции.ContainerProperties properties = new( id: "customers", partitionKeyPaths: keyPaths );
CreateContainerIfNotExistsAsync
Используйте метод для предоставления свойств контейнера и получения контейнера. Этот метод будет асинхронно создавать контейнер, если он еще не существует в базе данных. Возвращает результат в виде выходныхGetContainerAsync
данных метода.return await database.CreateContainerIfNotExistsAsync( containerProperties: properties );
Удалите весь код в методе
ManageCustomerAsync
.Чтобы выполнить следующие действия, добавьте этот код в
ManageCustomerAsync
метод.Асинхронно вызовите
GetContainerAsync
метод и сохраните результат в переменной с именемcontainer
.Container container = await GetContainerAsync();
Создайте новую переменную с именем
id
, которая используетKebaberize
метод из Humanizer для преобразованияname
параметра метода.string id = name.Kebaberize();
Примечание.
Метод
Kebaberize
заменит все пробелы дефисами и перевернет текст в нижний регистр.Создайте анонимный типизированный элемент с помощью
name
state
параметров метода иcountry
параметров метода и переменнойid
. Сохраните элемент в виде переменной с именемcustomer
.var customer = new { id = id, name = name, address = new { state = state, country = country } };
Используйте асинхронный
CreateItemAsync
метод контейнера, чтобы создать новый элемент в контейнере и назначить метаданные ответа HTTP переменной с именемresponse
.var response = await container.CreateItemAsync(customer);
Напишите значения переменных
response
StatusCode
иRequestCharge
свойств в консоль. Также записывает значение переменнойid
.Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RUs");
Сохраните файл CosmosHandler.cs .
Вернитесь в терминал, снова запустите приложение.
dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
Выходные данные команды должны включать состояние и плату за запрос для операции.
[Created] mica-pereira 7.05 RUs
Примечание.
Плата за запрос может отличаться.
Запустите приложение еще раз.
dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
На этот раз программа должна завершиться сбоем. Если прокрутить сообщение об ошибке, вы увидите, что сбой произошел из-за конфликта в уникальном идентификаторе элементов.
Unhandled exception: Microsoft.Azure.Cosmos.CosmosException : Response status code does not indicate success: Conflict (409);Reason: ( Errors : [ "Resource with specified id or name already exists." ] );
Получение элемента с помощью пакета SDK
Теперь, когда вы создали первый элемент в контейнере, вы можете использовать тот же пакет SDK для получения элемента. Здесь вы будете запрашивать и указывать на чтение элемента, чтобы сравнить разницу в потреблении единиц запросов (ЕЗ).
Вернитесь к файлу CosmosHandler.cs или откройте его.
Удалите все строки кода из
ManageCustomerAsync
метода, кроме первых двух строк.public static async Task ManageCustomerAsync(string name, string email, string state, string country) { Container container = await GetContainerAsync(); string id = name.Kebaberize(); }
Чтобы выполнить следующие действия, добавьте этот код в
ManageCustomerAsync
метод.Используйте асинхронный
CreateItemAsync
метод контейнера, чтобы создать новый элемент в контейнере и назначить метаданные ответа HTTP переменной с именемresponse
.var response = await container.CreateItemAsync(customer);
Создайте новую строку с именем
sql
SQL-запроса, чтобы получить элементы, в которых фильтр (@id
) совпадает.string sql = @" SELECT * FROM customers c WHERE c.id = @id ";
Создайте новую
QueryDefinition
переменную с именемquery
, передаваемую в строку вsql
качестве единственного параметра запроса. Кроме того, используйтеWithParameter
метод жидкости для применения значения переменнойid
к параметру@id
.var query = new QueryDefinition( query: sql ) .WithParameter("@id", id);
Используйте универсальный
GetItemQueryIterator<>
метод и переменную для создания итератораquery
, который получает данные из Azure Cosmos DB. Храните итератор в переменной с именемfeed
. Обтекайте все это выражение в инструкции using, чтобы удалить итератор позже.using var feed = container.GetItemQueryIterator<dynamic>( queryDefinition: query );
Асинхронно вызовите
ReadNextAsync
метод переменнойfeed
и сохраните результат в переменной с именемresponse
.var response = await feed.ReadNextAsync();
Напишите значения переменных
response
StatusCode
иRequestCharge
свойств в консоль. Также записывает значение переменнойid
.Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RUs");
Сохраните файл CosmosHandler.cs .
Вернитесь в терминал, запустите приложение, чтобы прочитать один элемент с помощью SQL-запроса.
dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
Выходные данные команды должны указывать на то, что запрос требует несколько единиц запроса (ЕЗ).
[OK] mica-pereira 2.82 RUs
Вернитесь в файл CosmosHandler.cs , удалите все строки кода из
ManageCustomerAsync
метода еще раз, за исключением первых двух строк.public static async Task ManageCustomerAsync(string name, string email, string state, string country) { Container container = await GetContainerAsync(); string id = name.Kebaberize(); }
Чтобы выполнить следующие действия, добавьте этот код в
ManageCustomerAsync
метод.Создайте новый экземпляр
PartitionKeyBuilder
, добавивstate
параметры вcountry
качестве значения ключа секции с несколькими частью.var partitionKey = new PartitionKeyBuilder() .Add(country) .Add(state) .Build();
Используйте метод контейнера, чтобы указывать на чтение элемента из контейнера
ReadItemAsync<>
с помощьюid
переменных иpartitionKey
переменных. Сохраните результат в переменной с именемresponse
.var response = await container.ReadItemAsync<dynamic>( id: id, partitionKey: partitionKey );
Напишите значения переменных
response
StatusCode
иRequestCharge
свойств в консоль. Также записывает значение переменнойid
.Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RU");
Сохраните файл CosmosHandler.cs еще раз.
Вернитесь в терминал, запустите приложение еще раз, чтобы указать на чтение одного элемента.
dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
Выходные данные команды должны указывать на то, что запросу требуется один ЕЗ.
[OK] mica-pereira 1 RUs
Создание транзакции с помощью пакета SDK
Наконец, вы принимаете созданный элемент, считываете этот элемент и создаете другой связанный элемент в рамках одной транзакции с помощью пакета SDK Azure для .NET.
Вернитесь к файлу CosmosHandler.cs или откройте его.
Удалите эти строки кода из
ManageCustomerAsync
метода.var response = await container.ReadItemAsync<dynamic>( id: id, partitionKey: partitionKey ); Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RUs");
Чтобы выполнить следующие действия, добавьте этот новый код в
ManageCustomerAsync
метод.Создайте анонимный типизированный элемент с помощью
name
state
параметров метода иcountry
параметров метода и переменнойid
. Сохраните элемент в виде переменной с именемcustomerCart
. Этот элемент представляет корзину покупок в режиме реального времени для клиента, который в настоящее время пуст.var customerCart = new { id = $"{Guid.NewGuid()}", customerId = id, items = new string[] {}, address = new { state = state, country = country } };
Создайте новый анонимный типизированный элемент с помощью
name
state
параметров метода иcountry
параметров метода и переменнойid
. Сохраните элемент в виде переменной с именемcustomerCart
. Этот элемент представляет сведения о доставке и контактных данных для клиента.var customerContactInfo = new { id = $"{id}-contact", customerId = id, email = email, location = $"{state}, {country}", address = new { state = state, country = country } };
Создайте пакет с помощью метода контейнера
CreateTransactionalBatch
, передавающегоpartitionKey
переменную. Сохраните пакет в переменной с именемbatch
. Используйте методы fluent для выполнения следующих действий:Способ Параметр ReadItem
id
строковая переменнаяCreateItem
customerCart
переменная анонимного типаCreateItem
customerContactInfo
переменная анонимного типаvar batch = container.CreateTransactionalBatch(partitionKey) .ReadItem(id) .CreateItem(customerCart) .CreateItem(customerContactInfo);
Используйте метод пакета
ExecuteAsync
для запуска транзакции. Сохраните результат в переменной с именемresponse
.using var response = await batch.ExecuteAsync();
Напишите значения переменных
response
StatusCode
иRequestCharge
свойств в консоль. Также записывает значение переменнойid
.Console.WriteLine($"[{response.StatusCode}]\t{response.RequestCharge} RUs");
Сохраните файл CosmosHandler.cs еще раз.
Вернитесь в терминал, запустите приложение еще раз, чтобы указать на чтение одного элемента.
dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
Выходные данные команды должны отображать единицы запроса, используемые для всей транзакции.
[OK] 16.05 RUs
Примечание.
Плата за запрос может отличаться.
Проверка окончательных данных в обозревателе данных
Чтобы упаковать вещи, используйте обозреватель данных в портал Azure для просмотра данных и контейнера, созданного в этом руководстве.
Перейдите к существующей учетной записи API для NoSQL в портал Azure.
В меню ресурсов выберите Обозреватель данных.
На странице обозревателя данных разверните
cosmicworks
базу данных и выберитеcustomers
контейнер.На панели команд выберите новый SQL-запрос.
В редакторе запросов обратите внимание на эту строку запроса SQL.
SELECT * FROM c
Выберите "Выполнить запрос" , чтобы запустить запрос и просмотреть результаты.
Результаты должны содержать массив JSON с тремя элементами, созданными в этом руководстве. Обратите внимание, что все элементы имеют одно и то же значение ключа иерархической секции, но уникальные поля идентификатора. Пример выходных данных, включенных, усечен для краткости.
[ { "id": "mica-pereira", "name": "Mica Pereira", "address": { "state": "Washington", "country": "United States" }, ... }, { "id": "33d03318-6302-4559-b5c0-f3cc643b2f38", "customerId": "mica-pereira", "items": [], "address": { "state": "Washington", "country": "United States" }, ... }, { "id": "mica-pereira-contact", "customerId": "mica-pereira", "email": null, "location": "Washington, United States", "address": { "state": "Washington", "country": "United States" }, ... } ]
Очистка ресурсов
При отсутствии необходимости удалите базу данных, используемую в этом руководстве. Для этого перейдите на страницу учетной записи, выберите обозреватель данных, выберите cosmicworks
базу данных и нажмите кнопку "Удалить".