Azure Cosmos DB .NET SDK v3 を使用するようにアプリケーションを移行する

適用対象: NoSQL

重要

Azure Cosmos DB .NET SDK v3 の詳細については、リリース ノート.NET GitHub リポジトリ、.NET SDK v3 のパフォーマンスに関するヒント、およびトラブルシューティング ガイドを参照してください。

この記事では、既存の .NET アプリケーションを、NoSQL 用 API の新しい Azure Cosmos DB .NET SDK v3 にアップグレードする際の考慮事項をいくつか取り上げます。 Azure Cosmos DB .NET SDK v3 は、Microsoft.Azure.Azure Cosmos DB 名前空間に対応しています。 次のいずれかの Azure Cosmos DB .NET SDK からアプリケーションを移行する場合は、このドキュメントに記載されている情報を使用できます。

  • NoSQL 用 API の Azure Cosmos DB .NET Framework SDK v2
  • NoSQL 用 API の Azure Cosmos DB .NET Core SDK v2

この記事の手順は、現在は NoSQL 用 API の Azure Cosmos DB .NET SDK v3 の一部である、次の外部ライブラリを移行する場合にも役立ちます。

  • .NET 変更フィード プロセッサ ライブラリ 2.0
  • .NET バルク エグゼキューター ライブラリ 1.1 以上

.NET V3 SDK の新機能

次のように、v3 SDK では多くのユーザビリティとパフォーマンスが向上しています。

  • 直感的なプログラミング モデルの名前付け
  • .NET Standard 2.0 **
  • ストリーム API サポートによるパフォーマンスの向上
  • URI ファクトリへの必要性に置き換わる Fluent 階層
  • 変更フィード プロセッサ ライブラリの組み込みサポート
  • 一括操作の組み込みサポート
  • 単体テストを容易にするためのモック可能な API
  • トランザクション バッチおよび Blazor のサポート
  • プラグ可能なシリアライザー
  • 非パーティション分割および自動スケーリング コンテナーのスケーリング

** SDK は、既存の Azure Cosmos DB .NET Framework および .NET Core SDK を単一の .NET SDK に統合する .NET Standard 2.0 を対象としています。 .NET Standard 2.0 を実装する任意のプラットフォームで .NET SDK を使用できます。これには、.NET Framework 4.6.1 以上および .NET Core 2.0 以上のアプリケーションが含まれます。

ネットワーク、再試行ロジック、および下位レベルの SDK はほとんど変わっていません。

Azure Cosmos DB .NET SDK v3 はオープン ソースになりました。 どんな pull request でも歓迎します。GitHub で問題をログに記録し、フィードバックを追跡します。カスタマー エクスペリエンスを向上させるあらゆる機能に対応するよう努力します。

.NET v3 SDK に移行する理由

多くのユーザビリティとパフォーマンスの向上に加え、最新の SDK で行われた新機能への投資が、以前のバージョンにバックポートされることはありません。 v2 SDK は現在メンテナンス モードになっています。 最適な開発環境を確保するために、常に最新バージョンの SDK から始めることをお勧めします。

v2 SDK から v3 SDK への名前のメジャー変更

NoSQL 用 API の API 名前付け規則に合わせて、.NET 3.0 SDK 全体に次の名前変更が適用されています。

  • DocumentClient の名前が CosmosClient に変更されました
  • Collection の名前が Container に変更されました
  • Document の名前が Item に変更されました

すべてのリソース オブジェクトの名前は追加のプロパティを使用して変更されます。これには、わかりやすくするためにリソース名が含まれています。

主なクラス名の変更の一部を次に示します。

.NET v2 SDK .NET v3 SDK
Microsoft.Azure.Documents.Client.DocumentClient Microsoft.Azure.Cosmos.CosmosClient
Microsoft.Azure.Documents.Client.ConnectionPolicy Microsoft.Azure.Cosmos.CosmosClientOptions
Microsoft.Azure.Documents.Client.DocumentClientException Microsoft.Azure.Cosmos.CosmosException
Microsoft.Azure.Documents.Client.Database Microsoft.Azure.Cosmos.DatabaseProperties
Microsoft.Azure.Documents.Client.DocumentCollection Microsoft.Azure.Cosmos.ContainerProperties
Microsoft.Azure.Documents.Client.RequestOptions Microsoft.Azure.Cosmos.ItemRequestOptions
Microsoft.Azure.Documents.Client.FeedOptions Microsoft.Azure.Cosmos.QueryRequestOptions
Microsoft.Azure.Documents.Client.StoredProcedure Microsoft.Azure.Cosmos.StoredProcedureProperties
Microsoft.Azure.Documents.Client.Trigger Microsoft.Azure.Cosmos.TriggerProperties
Microsoft.Azure.Documents.SqlQuerySpec Microsoft.Azure.Cosmos.QueryDefinition

.NET v3 SDK で置き換えられたクラス

3\.0 SDK で、次のクラスが置き換えられました。

  • Microsoft.Azure.Documents.UriFactory

Microsoft.Azure.Documents.UriFactory クラスは Fluent Design に置き換えられました。

Container container = client.GetContainer(databaseName,containerName);
ItemResponse<SalesOrder> response = await this._container.CreateItemAsync(
        salesOrder,
        new PartitionKey(salesOrder.AccountNumber));

  • Microsoft.Azure.Documents.Document

.NET v3 SDK を使用すると、ユーザーはカスタム シリアル化エンジンを構成できます。このため、Document 型の直接的な置き換えはありません。 Newtonsoft.Json (既定のシリアル化エンジン) を使用すると、JObject で同じ機能を実現できます。 別のシリアル化エンジンを使用する場合は、その基本 json ドキュメント型 (例: System.Text.Json の場合は JsonDocument) を使用できます。 ジェネリック型に頼るのではなく、項目のスキーマを反映する C# 型を使用することをお勧めします。

  • Microsoft.Azure.Documents.Resource

Resource の直接の置き換えはありません。ドキュメントに使用された場合は、Document のガイダンスに従ってください。

  • Microsoft.Azure.Documents.AccessCondition

IfNoneMatch または IfMatch は、Microsoft.Azure.Cosmos.ItemRequestOptions で直接使用できるようになりました。

項目 ID 生成の変更

.NET v3 SDK で項目 ID が自動的に設定されなくなりました。 そのため、項目 ID には、生成された ID を明示的に含める必要があります。 次の例を参照してください。

[JsonProperty(PropertyName = "id")]
public Guid Id { get; set; }

接続モードの既定の動作の変更

SDK v3 は既定で直接 + TCP の接続モードに設定されるようになりました。これに対し、v2 SDK はゲートウェイ + HTTPS の接続モードに既定で設定されていました。 この変更により、パフォーマンスとスケーラビリティが強化されます。

FeedOptions の変更 (v3.0 SDK では QueryRequestOptions)

SDK v2 の FeedOptions クラスの名前が SDK v3 で QueryRequestOptions に変更されました。クラス内のいくつかのプロパティの名前や既定値は変更されたか、完全に削除されています。

.NET v2 SDK .NET v3 SDK
FeedOptions.MaxDegreeOfParallelism QueryRequestOptions.MaxConcurrency - 既定値と関連する動作は同じままですが、並列クエリの実行中にクライアント側で実行される操作は並列処理なしで順次行われます。
FeedOptions.PartitionKey QueryRequestOptions.PartitionKey - 動作が維持されます。
FeedOptions.EnableCrossPartitionQuery 削除されます。 SDK 3.0 の既定の動作で、特にプロパティを有効にしなくてもクロスパーティション クエリが実行されるようになります。
FeedOptions.PopulateQueryMetrics 削除されます。 既定で有効になり、診断の一部になります。
FeedOptions.RequestContinuation 削除されます。 クエリ メソッド自体に昇格されました。
FeedOptions.JsonSerializerSettings 削除されます。 詳細については、シリアル化をカスタマイズする方法を参照してください。
FeedOptions.PartitionKeyRangeId 削除されます。 クエリ メソッドへの入力として FeedRange を使用することで、同じ結果を得ることができます。
FeedOptions.DisableRUPerMinuteUsage 削除されます。

クライアントの構築

.NET SDK v3 により、SDK v2 URI ファクトリへの必要性に置き換わる Fluent CosmosClientBuilder クラスが提供されます。

Fluent Design によって、内部的に URL が構築され、DocumentClientDatabaseName、および DocumentCollection ではなく、単一の Container オブジェクトを渡せるようになります。

次の例では、強力な ConsistencyLevel と優先される場所の一覧を使用して、新しい CosmosClientBuilder を作成します。

CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder(
    accountEndpoint: "https://testcosmos.documents.azure.com:443/",
    authKeyOrResourceToken: "SuperSecretKey")
.WithConsistencyLevel(ConsistencyLevel.Strong)
.WithApplicationRegion(Regions.EastUS);
CosmosClient client = cosmosClientBuilder.Build();

例外

操作時のエラー シグナルの生成に v2 SDK が DocumentClientException を使用していた場合、v3 SDK では、StatusCodeDiagnostics や他の応答関連情報を公開する CosmosException を使用します。 ToString() を使用すると、次のように、すべての完全な情報がシリアル化されます。

catch (CosmosException ex)
{
    HttpStatusCode statusCode = ex.StatusCode;
    CosmosDiagnostics diagnostics = ex.Diagnostics;
    // store diagnostics optionally with diagnostics.ToString();
    // or log the entire error details with ex.ToString();
}

診断

v2 SDK では、RequestDiagnosticsString プロパティを使用した直接のみの診断がありましたが、v3 SDK では、より高度で、直接モードに限定されない、すべての応答と例外で使用できる Diagnostics を使用します。 これには、操作のために SDK に費やした時間だけでなく、操作がアクセスしたリージョンも含まれます。

try
{
    ItemResponse<MyItem> response = await container.ReadItemAsync<MyItem>(
                    partitionKey: new PartitionKey("MyPartitionKey"),
                    id: "MyId");
    
    TimeSpan elapsedTime = response.Diagnostics.GetElapsedTime();
    if (elapsedTime > somePreDefinedThreshold)
    {
        // log response.Diagnostics.ToString();
        IReadOnlyList<(string region, Uri uri)> regions = response.Diagnostics.GetContactedRegions();
    }
}
catch (CosmosException cosmosException) {
    string diagnostics = cosmosException.Diagnostics.ToString();
    
    TimeSpan elapsedTime = cosmosException.Diagnostics.GetElapsedTime();
    
    IReadOnlyList<(string region, Uri uri)> regions = cosmosException.Diagnostics.GetContactedRegions();
    
    // log cosmosException.ToString()
}

ConnectionPolicy

ConnectionPolicy の一部の設定名が、CosmosClientOptions に変更または置換されました。

.NET v2 SDK .NET v3 SDK
EnableEndpointRediscovery LimitToEndpoint - 値が逆になりました。EnableEndpointRediscoverytrue に設定されていた場合、LimitToEndpointfalse に設定する必要があります。 この設定を使用する前に、クライアントに与える影響を理解しておく必要があります。
ConnectionProtocol 削除されます。 プロトコルは、ゲートウェイ (HTTPS) または直接 (TCP) のいずれかのモードに関連付けられています。 HTTPS プロトコルを使用したダイレクト モードは現在、V3 SDK ではサポートされていません。TCP プロトコルを使用することをお勧めします。
MediaRequestTimeout 削除されます。 アタッチがサポートされなくなりました。
SetCurrentLocation CosmosClientOptions.ApplicationRegion を使用して、同じ効果を実現できます。
PreferredLocations CosmosClientOptions.ApplicationPreferredRegions を使用して、同じ効果を実現できます。
UserAgentSuffix CosmosClientBuilder.ApplicationName を使用して、同じ効果を実現できます。
UseMultipleWriteLocations 削除されます。 SDK により、アカウントが複数の書き込みエンドポイントをサポートしているかどうかが自動的に検出されます。

インデックス作成ポリシー

インデックス作成ポリシーでは、これらのプロパティの設定はできません。 指定がない場合、これらのプロパティの値は次のようになります。

プロパティ名 新しい値 (設定不可)
Kind range
dataType String および Number

パスを含めたり除外したりするためのインデックス作成ポリシーの例については、こちらのセクションを参照してください。 クエリ エンジンの改良により、古いバージョンの SDK であっても、これらのプロパティの設定がパフォーマンスに影響することはありません。

セッション トークン

セッション トークンがヘッダーであるために、セッション トークンをキャプチャする必要があった、v2 SDK が応答のセッション トークンを ResourceResponse.SessionToken として公開していたケースでは、v3 SDK ではその値を任意の応答の Headers.Session プロパティで公開します。

Timestamp

Document が使用できなくなったため、v2 SDK がドキュメントのタイムスタンプを Timestamp プロパティで公開していた場合、ユーザーは _tsTimestampをそのモデルのプロパティにマップできます。

OpenAsync

v2 SDK クライアントのウォームアップに OpenAsync() を使用していたユース ケースでは、v3 SDK クライアントのOpenAsync()の両方を CreateAndInitializeAsync を使用して実行できます。

v3 SDK からの Change Feed Processor API の直接の使用

V3 SDK には Change Feed Processor API のサポートが組み込まれており、同じ SDK を使用してアプリケーションおよび変更フィード プロセッサの実装をビルドすることができます。 以前は、別個の変更フィード プロセッサ ライブラリを使用する必要がありました。

詳細については、変更フィード プロセッサ ライブラリから Azure Cosmos DB .NET v3 SDK に移行する方法に関するページを参照してください

変更フィードのクエリ

v3 SDK で変更フィードのクエリを実行すると、変更フィードのプル モデルが使用されていると見なされます。 構成を移行するには、次の表に従います。

.NET v2 SDK .NET v3 SDK
ChangeFeedOptions.PartitionKeyRangeId FeedRange - 並列処理を実現するために、変更フィード FeedRanges を読み取ることができます。 これは必須のパラメーターではなくなったため、コンテナー全体の変更フィードを簡単に読み取 ることができます。
ChangeFeedOptions.PartitionKey FeedRange.FromPartitionKey - 目的のパーティション キーを表す FeedRange を使用して、そのパーティション キー値の変更フィードを読み取ることができます。
ChangeFeedOptions.RequestContinuation ChangeFeedStartFrom.Continuation - 変更フィード反復子は、継続を保存し、新しい反復子の作成時に使用することで、いつでも停止および再開できます。
ChangeFeedOptions.StartTime ChangeFeedStartFrom.Time
ChangeFeedOptions.StartFromBeginning ChangeFeedStartFrom.Beginning
ChangeFeedOptions.MaxItemCount ChangeFeedRequestOptions.PageSizeHint - 変更フィード反復子は、継続を保存し、新しい反復子の作成時に使用することで、いつでも停止および再開できます。
IDocumentQuery.HasMoreResults response.StatusCode == HttpStatusCode.NotModified - 変更フィードは概念的に無限であるため、より多くの結果が得られる可能性があります。 応答に HttpStatusCode.NotModified 状態コードが含まれている場合は、現時点で読み取る新しい変更がないことを意味します。 これを使用して、継続を停止して保存したり、一時的にスリープまたは待機してから再度 ReadNextAsync を呼び出して新しい変更をテストすることができます。
分割処理 ユーザーが変更フィードを読み取るときに分割例外を処理する必要がなくなりました。分割は、ユーザーの操作を必要とせずに透過的に処理されます。

V3 SDK からのバルク エグゼキューター ライブラリの直接の使用

v3 SDK にはバルク エグゼキューター ライブラリのサポートが組み込まれているため、同じ SDK を使用してアプリケーションをビルドし、一括操作を実行することができます。 以前は、別個のバルク エグゼキューター ライブラリを使用する必要がありました。

詳細については、バルク エグゼキューター ライブラリから Azure Cosmos DB .NET V3 SDK のバルク サポートに移行する方法に関するページを参照してください

シリアル化をカスタマイズする

.NET V2 SDK を使用すると、結果ドキュメントの逆シリアル化に使用される操作レベルで、RequestOptionsJsonSerializerSettings を設定できます。

// .NET V2 SDK
var result = await container.ReplaceDocumentAsync(document, new RequestOptions { JsonSerializerSettings = customSerializerSettings })

.NET SDK v3 には、シリアル化エンジンを完全にカスタマイズするためのシリアライザー インターフェイス、またはクライアント構築の一環としてより汎用的な シリアル化オプションが用意されています。

操作レベルでシリアル化をカスタマイズするには、Stream API を使用します。

// .NET V3 SDK
using(Response response = await this.container.ReplaceItemStreamAsync(stream, "itemId", new PartitionKey("itemPartitionKey"))
{

    using(Stream stream = response.ContentStream)
    {
        using (StreamReader streamReader = new StreamReader(stream))
        {
            // Read the stream and do dynamic deserialization based on type with a custom Serializer
        }
    }
}

コード スニペットの比較

次のコード スニペットは、.NET v2 および v3 SDK のリソースの作成方法の違いを示しています。

データベース操作

データベースを作成する

// Create database with no shared provisioned throughput
DatabaseResponse databaseResponse = await client.CreateDatabaseIfNotExistsAsync(DatabaseName);
Database database = databaseResponse;
DatabaseProperties databaseProperties = databaseResponse;

// Create a database with a shared manual provisioned throughput
string databaseIdManual = new string(DatabaseName + "_SharedManualThroughput");
database = await client.CreateDatabaseIfNotExistsAsync(databaseIdManual, ThroughputProperties.CreateManualThroughput(400));

// Create a database with shared autoscale provisioned throughput
string databaseIdAutoscale = new string(DatabaseName + "_SharedAutoscaleThroughput");
database = await client.CreateDatabaseIfNotExistsAsync(databaseIdAutoscale, ThroughputProperties.CreateAutoscaleThroughput(4000));

ID によってデータベースを読み取る

// Read a database
Console.WriteLine($"{Environment.NewLine} Read database resource: {DatabaseName}");
database = client.GetDatabase(DatabaseName);
Console.WriteLine($"{Environment.NewLine} database { database.Id.ToString()}");

// Read all databases
string findQueryText = "SELECT * FROM c";
using (FeedIterator<DatabaseProperties> feedIterator = client.GetDatabaseQueryIterator<DatabaseProperties>(findQueryText))
{
    while (feedIterator.HasMoreResults)
    {
        FeedResponse<DatabaseProperties> databaseResponses = await feedIterator.ReadNextAsync();
        foreach (DatabaseProperties _database in databaseResponses)
        {
            Console.WriteLine($"{ Environment.NewLine} database {_database.Id.ToString()}");
        }
    }
}

データベースの削除

// Delete a database
await client.GetDatabase(DatabaseName).DeleteAsync();
Console.WriteLine($"{ Environment.NewLine} database {DatabaseName} deleted.");

// Delete all databases in an account
string deleteQueryText = "SELECT * FROM c";
using (FeedIterator<DatabaseProperties> feedIterator = client.GetDatabaseQueryIterator<DatabaseProperties>(deleteQueryText))
{
    while (feedIterator.HasMoreResults)
    {
        FeedResponse<DatabaseProperties> databaseResponses = await feedIterator.ReadNextAsync();
        foreach (DatabaseProperties _database in databaseResponses)
        {
            await client.GetDatabase(_database.Id).DeleteAsync();
            Console.WriteLine($"{ Environment.NewLine} database {_database.Id} deleted");
        }
    }
}

コンテナーの操作

コンテナーを作成する (自動スケーリング + 有効期限付きの Time to Live)

private static async Task CreateManualThroughputContainer(Database database)
{
    // Set throughput to the minimum value of 400 RU/s manually configured throughput
    string containerIdManual = ContainerName + "_Manual";
    ContainerResponse container = await database.CreateContainerIfNotExistsAsync(
        id: containerIdManual,
        partitionKeyPath: partitionKeyPath,
        throughput: 400);
}

// Create container with autoscale
private static async Task CreateAutoscaleThroughputContainer(Database database)
{
    string autoscaleContainerId = ContainerName + "_Autoscale";
    ContainerProperties containerProperties = new ContainerProperties(autoscaleContainerId, partitionKeyPath);

    Container container = await database.CreateContainerIfNotExistsAsync(
        containerProperties: containerProperties,
        throughputProperties: ThroughputProperties.CreateAutoscaleThroughput(autoscaleMaxThroughput: 4000);
}

// Create a container with TTL Expiration
private static async Task CreateContainerWithTtlExpiration(Database database)
{
    string containerIdManualwithTTL = ContainerName + "_ManualTTL";

    ContainerProperties properties = new ContainerProperties
        (id: containerIdManualwithTTL,
        partitionKeyPath: partitionKeyPath);

    properties.DefaultTimeToLive = (int)TimeSpan.FromDays(1).TotalSeconds; //expire in 1 day

    ContainerResponse containerResponse = await database.CreateContainerIfNotExistsAsync(containerProperties: properties);
    ContainerProperties returnedProperties = containerResponse;
}

コンテナーのプロパティを読み取る

private static async Task ReadContainerProperties(Database database)
{
    string containerIdManual = ContainerName + "_Manual";
    Container container = database.GetContainer(containerIdManual);
    ContainerProperties containerProperties = await container.ReadContainerAsync();
}

コンテナーを削除する

private static async Task DeleteContainers(Database database)
{
    string containerIdManual = ContainerName + "_Manual";

    // Delete a container
    await database.GetContainer(containerIdManual).DeleteContainerAsync();

    // Delete all CosmosContainer resources for a database
    using (FeedIterator<ContainerProperties> feedIterator = database.GetContainerQueryIterator<ContainerProperties>())
    {
        while (feedIterator.HasMoreResults)
        {
            foreach (ContainerProperties _container in await feedIterator.ReadNextAsync())
            {
                await database.GetContainer(_container.Id).DeleteContainerAsync();
                Console.WriteLine($"{Environment.NewLine}  deleted container {_container.Id}");
            }
        }
    }
}

項目とクエリの操作

項目を作成する

private static async Task CreateItemAsync(Container container)
{
    // Create a SalesOrder POCO object
    SalesOrder salesOrder1 = GetSalesOrderSample("Account1", "SalesOrder1");
    ItemResponse<SalesOrder> response = await container.CreateItemAsync(salesOrder1,
        new PartitionKey(salesOrder1.AccountNumber));
}

private static async Task RunBasicOperationsOnDynamicObjects(Container container)
{
    // Dynamic Object
    dynamic salesOrder = new
    {
        id = "SalesOrder5",
        AccountNumber = "Account1",
        PurchaseOrderNumber = "PO18009186470",
        OrderDate = DateTime.UtcNow,
        Total = 5.95,
    };
    Console.WriteLine("\nCreating item");
    ItemResponse<dynamic> response = await container.CreateItemAsync<dynamic>(
        salesOrder, new PartitionKey(salesOrder.AccountNumber));
    dynamic createdSalesOrder = response.Resource;
}

コンテナー内のすべての項目の読み取り

private static async Task ReadAllItems(Container container)
{
    // Read all items in a container
    List<SalesOrder> allSalesForAccount1 = new List<SalesOrder>();

    using (FeedIterator<SalesOrder> resultSet = container.GetItemQueryIterator<SalesOrder>(
        queryDefinition: null,
        requestOptions: new QueryRequestOptions()
        {
            PartitionKey = new PartitionKey("Account1"),
            MaxItemCount = 5
        }))
    {
        while (resultSet.HasMoreResults)
        {
            FeedResponse<SalesOrder> response = await resultSet.ReadNextAsync();
            SalesOrder salesOrder = response.First();
            Console.WriteLine($"\n1.3.1 Account Number: {salesOrder.AccountNumber}; Id: {salesOrder.Id}");
            allSalesForAccount1.AddRange(response);
        }
    }
}

クエリ項目

SqlQuerySpec に対する変更 (version 3.0 SDK の QueryDefinition)

SDK v2 の SqlQuerySpec クラスは、SDK v3 では QueryDefinition という名前に変更されました。

SqlParameterCollectionSqlParameter は削除されました。 QueryDefinition.WithParameter を使用するビルダー モデルをもつ QueryDefinition にパラメーターが追加されました。 ユーザーは QueryDefinition.GetQueryParameters を使用してパラメーターにアクセスできます。

private static async Task QueryItems(Container container)
{
    // Query for items by a property other than Id
    QueryDefinition queryDefinition = new QueryDefinition(
        "select * from sales s where s.AccountNumber = @AccountInput")
        .WithParameter("@AccountInput", "Account1");

    List<SalesOrder> allSalesForAccount1 = new List<SalesOrder>();
    using (FeedIterator<SalesOrder> resultSet = container.GetItemQueryIterator<SalesOrder>(
        queryDefinition,
        requestOptions: new QueryRequestOptions()
        {
            PartitionKey = new PartitionKey("Account1"),
            MaxItemCount = 1
        }))
    {
        while (resultSet.HasMoreResults)
        {
            FeedResponse<SalesOrder> response = await resultSet.ReadNextAsync();
            SalesOrder sale = response.First();
            Console.WriteLine($"\n Account Number: {sale.AccountNumber}; Id: {sale.Id};");
            allSalesForAccount1.AddRange(response);
        }
    }
}

項目を削除する

private static async Task DeleteItemAsync(Container container)
{
    ItemResponse<SalesOrder> response = await container.DeleteItemAsync<SalesOrder>(
        partitionKey: new PartitionKey("Account1"), id: "SalesOrder3");
}

変更フィードのクエリ

private static async Task QueryChangeFeedAsync(Container container)
{
    FeedIterator<SalesOrder> iterator = container.GetChangeFeedIterator<SalesOrder>(ChangeFeedStartFrom.Beginning(), ChangeFeedMode.Incremental);

    string continuation = null;
    while (iterator.HasMoreResults)
    {
        FeedResponse<SalesOrder> response = await iteratorForTheEntireContainer.ReadNextAsync();
    
        if (response.StatusCode == HttpStatusCode.NotModified)
        {
            // No new changes
            continuation = response.ContinuationToken;
            break;
        }
        else 
        {
            // Process the documents in response
        }
    }
}

次のステップ