次の方法で共有


チュートリアル: Azure Cosmos DB for NoSQL で .NET コンソール アプリケーションを開発する

適用対象: NoSQL

Azure SDK for .NET を使用すると、非同期の個別操作またはトランザクション バッチを使用して、NoSQL コンテナーの API にデータを追加できます。 このチュートリアルでは、コンテナーに複数の項目を追加する新しい .NET コンソール アプリケーションを作成するプロセスについて説明します。

このチュートリアルでは、次の作業を行う方法について説明します。

  • NoSQL 用 API を使用してデータベースを作成する
  • .NET コンソール アプリケーションを作成し、Azure SDK for .NET を追加する
  • NoSQL 用 API コンテナーに個々の項目を追加する
  • NoSQL 用 API コンテナーから効率的に項目を取得する
  • NoSQL 用 API コンテナー用にバッチ変更を含むトランザクションを作成する

前提条件

NoSQL 用 API リソースを作成する

まず、既存の NoSQL 用 API アカウントに空のデータベースを作成します。 後で Azure SDK for .NET を使用してコンテナーを作成します。

  1. Azure portal で既存の NoSQL 用 API アカウントに移動します。

  2. [リソース] メニューで [キー] を選択します。

    NoSQL 用 API アカウント ページのスクリーンショット。リソース メニューで [キー] オプションが強調表示されています。

  3. [キー] ページで、[URI] フィールドと [PRIMARY KEY] フィールドの値を確認して記録します。 これらの値は、チュートリアル全体で使用されます。

    [URI] と [PRIMARY KEY] フィールドが強調表示されている [キー] ページのスクリーンショット。

  4. リソース メニューで [Data Explorer] を選びます。

    リソース メニューで強調表示されている [データ エクスプローラー] オプションのスクリーンショット。

  5. [データ エクスプローラー] ページのコマンド バーで [新しいデータベース] オプションを選択します。

    データ エクスプローラーのコマンド バーの [新しいデータベース] オプションのスクリーンショット。

  6. [新しいデータベース] ダイアログで、次の設定を使用して新しいコンテナーを作成します。

    データベース ID cosmicworks
    データベースのスループットの種類 [手動]
    データベースのスループットの量 400

    データ エクスプローラーの [新しいデータベース] ダイアログのスクリーンショット。各フィールドにさまざまな値が表示されています。

  7. [OK] を選び、データベースを作成します。

.NET コンソール アプリケーションを作成する

次に、新しい .NET コンソール アプリケーションを作成し、NuGet の Microsoft.Azure.Cosmos ライブラリを使用して Azure SDK for .NET をインポートします。

  1. 空のディレクトリでターミナルを開きます。

  2. console 組み込みテンプレートを使用して新しいコンソール アプリケーションを作成します

    dotnet new console --langVersion preview
    
  3. NuGet から Microsoft.Azure.Cosmos パッケージの 3.31.1 プレビュー バージョンを追加します。

    dotnet add package Microsoft.Azure.Cosmos --version 3.31.1-preview
    
  4. また、NuGet から System.CommandLine パッケージのプレリリース バージョンを追加します。

    dotnet add package System.CommandLine --prerelease
    
  5. また、NuGet から Humanizer パッケージを追加します。

    dotnet add package Humanizer
    
  6. コンソール アプリケーション プロジェクトをビルドします。

    dotnet build
    
  7. 現在のプロジェクト フォルダーをワークスペースとして使用して Visual Studio Code を開きます。

    ヒント

    ターミナルで code . を実行して Visual Studio Code を開くと、現在のワークスペースとして作業ディレクトリを自動的に開くことができます。

  8. Program.cs ファイルに移動して開きます。 ファイル内の既存のコードをすべて削除します。

  9. このコードをファイルに追加して、System.CommandLine ライブラリを使用して、--first および --last のオプションを介して渡された 2 つの文字列のコマンド ラインを解析します。

    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);
    

    注意

    このチュートリアルでは、コマンド ライン パーサーのしくみを理解することは必ずしも重要ではありません。 このパーサーには、アプリケーションの実行時に指定できる 4 つのオプションがあります。 これらのオプションのうち 3 つは、ID およびパーティション キー フィールドの構築に使用されるため、必須です。

  10. この時点では、静的な CosmosHandler.ManageCustomerAsync メソッドをまだ定義していないため、プロジェクトはビルドされません。

  11. Program.cs ファイルを保存します。

SDK を使用してコンテナーに項目を追加する

次に、個々の操作を使用して、NoSQL 用 API コンテナーに項目を追加します。 このセクションでは、CosmosHandler.ManageCustomerAsync メソッドを定義します。

  1. 新しい CosmosHandler.cs ファイルを作成します。

  2. CosmosHandler.cs ファイル内に、HumanizerMicrosoft.Azure.Cosmos の名前空間の新しい using ディレクティブを追加します。

    using Humanizer;
    using Microsoft.Azure.Cosmos;
    
  3. CosmosHandler という名前の新しい静的クラスを作成します。

    public static class CosmosHandler
    { }
    
  4. このアプリが機能することを確認するためだけに、静的な ManageCustomerAsync メソッドの短い実装を作成して、コマンド ライン入力を出力します。

    public static async Task ManageCustomerAsync(string name, string email, string state, string country)
    {
        await Console.Out.WriteLineAsync($"Hello {name} of {state}, {country}!");
    }
    
  5. CosmosHandler.cs ファイルを保存します。

  6. ターミナルに戻り、アプリケーションを実行します。

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  7. コマンドの出力は楽しいあいさつになります。

    Hello Mica Pereira of Washington, United States!
    
  8. CosmosHandler.cs ファイルに戻ります。

  9. 静的 CosmosHandler クラス内に、_client という名前の CosmosClient 型の新しい private static readonly メンバーを追加します。

    private static readonly CosmosClient _client;
    
  10. CosmosHandler クラスの新しい静的コンストラクターを作成します。

    static CosmosHandler()
    { }
    
  11. このコンストラクター内で、CosmosClient クラスの新しいインスタンスを作成し、ラボで前に記録した URIPRIMARY KEY の値を含む 2 つの文字列パラメーターを渡します。 この新しいインスタンスを _client メンバーに保存します。

    static CosmosHandler()
    {
        _client = new CosmosClient(
            accountEndpoint: "<uri>", 
            authKeyOrResourceToken: "<primary-key>"
        );
    }
    
  12. 静的 CosmosHandler クラス内に戻り、Container を返す GetContainerAsync という名前の新しい非同期メソッドを作成します。

    private static async Task<Container> GetContainerAsync()
    { }
    
  13. 次の手順では、GetContainerAsync メソッド内にこのコードを追加します。

    1. cosmicworks データベースを取得し、database という名前の変数に保存します。

      Database database = _client.GetDatabase("cosmicworks");
      
    2. 階層パーティション キー パスのリスト内に string 値の新しいジェネリック List<> を作成し、それを keyPaths という名前の変数に保存します。

      List<string> keyPaths = new()
      {
          "/address/country",
          "/address/state"
      };
      
    3. コンテナー (customers) の名前とパーティション キー パスのリストを使用して、新しい ContainerProperties 変数を作成します。

      ContainerProperties properties = new(
          id: "customers",
          partitionKeyPaths: keyPaths
      );
      
    4. CreateContainerIfNotExistsAsync メソッドを使用して、コンテナー プロパティを指定し、コンテナーを取得します。 このメソッドは、その名前の通り、コンテナーがデータベース内にまだ存在しない場合に非同期で作成します。 GetContainerAsync メソッドの出力として結果を返します。

      return await database.CreateContainerIfNotExistsAsync(
          containerProperties: properties
      );
      
  14. ManageCustomerAsync メソッド内のすべてのコードを削除します。

  15. 次の手順では、ManageCustomerAsync メソッド内にこのコードを追加します。

    1. GetContainerAsync メソッドを非同期的に呼び出して、その結果を container という名前の変数に保存します。

      Container container = await GetContainerAsync();
      
    2. id という名前の新しい変数を作成します。これは HumanizerKebaberize メソッドを使用して name メソッド パラメーターを変換します。

      string id = name.Kebaberize();
      

      注意

      Kebaberize メソッドは、すべてのスペースをハイフンに置き換え、テキストを小文字に変換します。

    3. namestatecountry の各メソッド パラメーターと id 変数を使用して、新しい匿名型の項目を作成します。 項目を customer という名前の変数として保存します。

      var customer = new {
          id = id,
          name = name,
          address = new {
              state = state,
              country = country
          }
      };
      
    4. コンテナーの非同期 CreateItemAsync メソッドを使用して、コンテナーに新しい項目を作成し、HTTP 応答メタデータを response という名前の変数に割り当てます。

      var response = await container.CreateItemAsync(customer);
      
    5. response 変数の StatusCode および RequestCharge の各プロパティの値をコンソールに書き込みます。 id 変数の値も書き込みます。

      Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RUs");
      
  16. CosmosHandler.cs ファイルを保存します。

  17. ターミナルに戻り、アプリケーションをもう一度実行します。

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  18. コマンドの出力には、操作の状態と要求の料金が含まれます。

    [Created]       mica-pereira    7.05 RUs
    

    注意

    要求の料金は異なる場合があります。

  19. アプリケーションをもう一度実行します。

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  20. 今回は、プログラムがクラッシュします。 エラー メッセージをスクロールすると、項目の一意識別子の競合が原因でクラッシュが発生したことがわかります。

    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 を使用してその項目を取得できます。 ここでは、項目に対してクエリとポイント読み取りを実行して、要求ユニット (RU) 消費量の違いを比較します。

  1. CosmosHandler.cs ファイルに戻るか、開きます。

  2. ManageCustomerAsync メソッドから、最初の 2 行を除き、すべてのコード行を削除します。

    public static async Task ManageCustomerAsync(string name, string email, string state, string country)
    {
        Container container = await GetContainerAsync();
    
        string id = name.Kebaberize();
    }
    
  3. 次の手順では、ManageCustomerAsync メソッド内にこのコードを追加します。

    1. コンテナーの非同期 CreateItemAsync メソッドを使用して、コンテナーに新しい項目を作成し、HTTP 応答メタデータを response という名前の変数に割り当てます。

      var response = await container.CreateItemAsync(customer);
      
    2. SQL クエリを使用して sql という名前の新しい文字列を作成し、フィルター (@id) が一致する項目を取得します。

      string sql = @"
      SELECT
          *
      FROM customers c
      WHERE c.id = @id
      ";
      
    3. query という名前の新しい QueryDefinition 変数を作成し、唯一のクエリ パラメーターとして sql 文字列を渡します。 また、WithParameter fluid メソッドを使用して、変数 id の値を @id パラメータに適用します。

      var query = new QueryDefinition(
          query: sql
      )
          .WithParameter("@id", id);
      
    4. GetItemQueryIterator<> ジェネリック メソッドと query 変数を使用して、Azure Cosmos DB からデータを取得する反復子を作成します。 この反復子を feed という名前の変数として保存します。 この式全体を using ステートメントでラップして、後で反復子を破棄します。

      using var feed = container.GetItemQueryIterator<dynamic>(
          queryDefinition: query
      );
      
    5. feed 変数の ReadNextAsync メソッドを非同期的に呼び出し、その結果を response という名前の変数に保存します。

      var response = await feed.ReadNextAsync();
      
    6. response 変数の StatusCode および RequestCharge の各プロパティの値をコンソールに書き込みます。 id 変数の値も書き込みます。

      Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RUs");
      
  4. CosmosHandler.cs ファイルを保存します。

  5. ターミナルに戻り、アプリケーションを実行し、SQL クエリを使用して 1 つの項目を読み取ります。

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  6. コマンドの出力には、クエリに複数の要求ユニット (RU) が必要であることが示されているはずです。

    [OK]    mica-pereira    2.82 RUs
    
  7. CosmosHandler.cs ファイルに戻り、ManageCustomerAsync メソッドから最初の 2 行を除くすべてのコード行をもう一度削除します。

    public static async Task ManageCustomerAsync(string name, string email, string state, string country)
    {
        Container container = await GetContainerAsync();
    
        string id = name.Kebaberize();
    }
    
  8. 次の手順では、ManageCustomerAsync メソッド内にこのコードを追加します。

    1. statecountry のパラメーターをマルチパート パーティション キーの値として追加して、PartitionKeyBuilder の新しいインスタンスを作成します。

      var partitionKey = new PartitionKeyBuilder()
          .Add(country)
          .Add(state)
          .Build();
      
    2. コンテナーの ReadItemAsync<> メソッドを使用して、idpartitionKey の変数を使用してコンテナーから項目をポイント読み取りします。 結果を response という名前の変数に保存します。

      var response = await container.ReadItemAsync<dynamic>(
          id: id, 
          partitionKey: partitionKey
      );
      
    3. response 変数の StatusCode および RequestCharge の各プロパティの値をコンソールに書き込みます。 id 変数の値も書き込みます。

      Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RU");
      
  9. CosmosHandler.cs ファイルをもう一度保存します。

  10. ターミナルに戻り、アプリケーションをもう 1 回実行して、1 つの項目をポイント読み取りします。

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  11. コマンドの出力には、クエリに 1 つの RU が必要であることが示されているはずです。

    [OK]    mica-pereira    1 RUs
    

SDK を使用してトランザクションを作成する

最後に、作成した項目を取得し、その項目を読み取り、Azure SDK for .NET を使用して 1 つのトランザクションの一部として別の関連項目を作成します。

  1. CosmosHandler.cs ファイルに戻るか、開きます。

  2. ManageCustomerAsync メソッドから次のコード行を削除します。

    var response = await container.ReadItemAsync<dynamic>(
        id: id, 
        partitionKey: partitionKey
    );
    
    Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RUs");
    
  3. 次の手順では、ManageCustomerAsync メソッド内にこのコードを追加します。

    1. namestatecountry の各メソッド パラメーターと id 変数を使用して、新しい匿名型の項目を作成します。 この項目を customerCart という名前の変数として保存します。 この項目は、現在空の顧客のリアルタイムのショッピング カートを表します。

      var customerCart = new {
          id = $"{Guid.NewGuid()}",
          customerId = id,
          items = new string[] {},
          address = new {
              state = state,
              country = country
          }
      };
      
    2. namestatecountry のメソッド パラメーターと id 変数を使用して、別の新しい匿名型の項目を作成します。 この項目を customerCart という名前の変数として保存します。 この項目は、顧客の発送先と連絡先情報を表します。

      var customerContactInfo = new {
          id = $"{id}-contact",
          customerId = id,
          email = email,
          location = $"{state}, {country}",
          address = new {
              state = state,
              country = country
          }
      };
      
    3. コンテナーの CreateTransactionalBatch メソッドを使用して新しいバッチを作成し、partitionKey 変数を渡します。 このバッチを batch という名前の変数として保存します。 fluent メソッドを使用して、次のアクションを実行します。

      方法 パラメーター
      ReadItem id 文字列変数
      CreateItem customerCart 匿名型変数
      CreateItem customerContactInfo 匿名型変数
      var batch = container.CreateTransactionalBatch(partitionKey)
          .ReadItem(id)
          .CreateItem(customerCart)
          .CreateItem(customerContactInfo);
      
    4. バッチの ExecuteAsync メソッドを使用してトランザクションを開始します。 結果を response という名前の変数に保存します。

      using var response = await batch.ExecuteAsync();
      
    5. response 変数の StatusCode および RequestCharge の各プロパティの値をコンソールに書き込みます。 id 変数の値も書き込みます。

      Console.WriteLine($"[{response.StatusCode}]\t{response.RequestCharge} RUs");
      
  4. CosmosHandler.cs ファイルをもう一度保存します。

  5. ターミナルに戻り、アプリケーションをもう 1 回実行して、1 つの項目をポイント読み取りします。

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  6. コマンドの出力には、トランザクション全体に使用される要求ユニットが表示されます。

    [OK]    16.05 RUs
    

    注意

    要求の料金は異なる場合があります。

データ エクスプローラーの最終的なデータを検証する

最後に、Azure portal のデータ エクスプローラーを使用して、このチュートリアルで作成したデータとコンテナーを表示します。

  1. Azure portal で既存の NoSQL 用 API アカウントに移動します。

  2. リソース メニューで [Data Explorer] を選びます。

    リソース メニューで強調表示されている [データ エクスプローラー] オプションのスクリーンショット。

  3. [データ エクスプローラー] ページで cosmicworks データベースを展開し、customers コンテナーを選びます。

    データベース ノード内の選択されたコンテナー ノードのスクリーンショット。

  4. コマンド バーで、[新しい SQL クエリ] を選びます。

    データ エクスプローラーのコマンド バーの [新しい SQL クエリ] オプションのスクリーンショット。

  5. クエリ エディターで、この SQL クエリ文字列を観察します。

    SELECT * FROM c
    
  6. [クエリの実行] を選択してクエリを実行し、結果を確認します。

    データ エクスプローラーのコマンド バーの [クエリの実行] オプションのスクリーンショット。

  7. 結果には、このチュートリアルで作成された 3 つの項目を含む JSON 配列が含まれています。 すべての項目の階層パーティション キーの値は同じですが、ID フィールドは一意であることを確認してください。 含まれている出力例は、簡潔にするために省略されています。

    [
      {
        "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 データベースを選択して、[削除] を選択します。