Migre seu aplicativo para usar o Azure Cosmos DB .NET SDK v3

APLICA-SE A: NoSQL

Importante

Para saber mais sobre o Azure Cosmos DB .NET SDK v3, consulte as Notas de versão, o repositório .NET GitHub, as Dicas de desempenho do .NET SDK v3 e o Guia de solução de problemas.

Este artigo destaca algumas das considerações de atualizar seu aplicativo .NET existente para o mais recente Azure Cosmos DB .NET SDK v3 para API para NoSQL. O Azure Cosmos DB .NET SDK v3 corresponde ao namespace Microsoft.Azure.Azure Cosmos DB. Você pode usar as informações fornecidas neste documento se estiver migrando seu aplicativo de qualquer um dos seguintes SDKs .NET do Azure Cosmos DB:

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

As instruções neste artigo também ajudam você a migrar as seguintes bibliotecas externas que agora fazem parte do Azure Cosmos DB .NET SDK v3 for API for NoSQL:

  • Biblioteca do processador de feed de alteração .NET 2.0
  • Biblioteca de executores em massa .NET 1.1 ou superior

O que há de novo no SDK do .NET V3

O SDK v3 contém muitas melhorias de usabilidade e desempenho, incluindo:

  • Nomenclatura intuitiva do modelo de programação
  • .NET Standard 2.0 **
  • Maior desempenho através do suporte à API de fluxo
  • Hierarquia fluente que substitui a necessidade de fábrica de URI
  • Suporte integrado para alterar a biblioteca do processador de alimentação
  • Suporte integrado para operações em massa
  • APIs simuláveis para testes de unidade mais fáceis
  • Lote transacional e suporte Blazor
  • Serializadores conectáveis
  • Dimensione contêineres não particionados e dimensione automaticamente

** O SDK destina-se ao .NET Standard 2.0 que unifica os SDKs existentes do Azure Cosmos DB, .NET Framework e .NET Core em um único SDK do .NET. Você pode usar o SDK do .NET em qualquer plataforma que implemente o .NET Standard 2.0, incluindo seus aplicativos .NET Framework 4.6.1+ e .NET Core 2.0+.

A maioria da rede, a lógica de repetição e os níveis mais baixos do SDK permanecem praticamente inalterados.

O Azure Cosmos DB .NET SDK v3 agora é de código aberto. Congratulamo-nos com quaisquer solicitações pull e registraremos problemas e rastrearemos feedback no GitHub. Trabalharemos para adotar todos os recursos que melhorem a experiência do cliente.

Por que migrar para o SDK do .NET v3

Além das inúmeras melhorias de usabilidade e desempenho, os novos investimentos em recursos feitos no SDK mais recente não serão reportados para versões mais antigas. O SDK v2 está atualmente no modo de manutenção. Para obter a melhor experiência de desenvolvimento, recomendamos sempre começar com a versão suportada mais recente do SDK.

Principais alterações de nome do SDK v2 para o SDK v3

As seguintes alterações de nome foram aplicadas em todo o SDK do .NET 3.0 para alinhar com as convenções de nomenclatura da API para NoSQL:

  • DocumentClient é renomeado para CosmosClient
  • Collection é renomeado para Container
  • Document é renomeado para Item

Todos os objetos de recurso são renomeados com propriedades adicionais, que incluem o nome do recurso para clareza.

A seguir estão algumas das principais alterações de nome de classe:

SDK do .NET v2 SDK do .NET v3
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

Classes substituídas no SDK do .NET v3

As seguintes classes foram substituídas no SDK 3.0:

  • Microsoft.Azure.Documents.UriFactory

A classe Microsoft.Azure.Documents.UriFactory foi substituída pelo design fluente.

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

  • Microsoft.Azure.Documents.Document

Como o SDK do .NET v3 permite que os usuários configurem um mecanismo de serialização personalizado, não há substituição direta para o Document tipo. Ao usar Newtonsoft.Json (mecanismo de serialização padrão), JObject pode ser usado para obter a mesma funcionalidade. Ao usar um mecanismo de serialização diferente, você pode usar seu tipo de documento json base (por exemplo, JsonDocument para System.Text.Json). A recomendação é usar um tipo C# que reflita o esquema de seus itens em vez de depender de tipos genéricos.

  • Microsoft.Azure.Documents.Resource

Não há substituição direta para Resource, nos casos em que foi usado para documentos, siga as orientações para Document.

  • Microsoft.Azure.Documents.AccessCondition

IfNoneMatch ou IfMatch estão agora disponíveis no direto Microsoft.Azure.Cosmos.ItemRequestOptions .

Alterações na geração de ID de item

A ID do item não é mais preenchida automaticamente no SDK do .NET v3. Portanto, o ID do item deve incluir especificamente um ID gerado. Veja o exemplo a seguir:

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

Comportamento padrão alterado para o modo de conexão

O SDK v3 agora usa como padrão os modos de conexão Direct + TCP em comparação com o SDK v2 anterior, que tinha como padrão os modos de conexões Gateway + HTTPS. Essa alteração oferece desempenho e escalabilidade aprimorados.

Alterações em FeedOptions (QueryRequestOptions no SDK v3.0)

A FeedOptions classe no SDK v2 agora foi renomeada para QueryRequestOptions no SDK v3 e, dentro da classe, várias propriedades tiveram alterações no nome e/ou valor padrão ou foram removidas completamente.

SDK do .NET v2 SDK do .NET v3
FeedOptions.MaxDegreeOfParallelism QueryRequestOptions.MaxConcurrency - O valor padrão e o comportamento associado permanecem os mesmos, as operações executadas do lado do cliente durante a execução da consulta paralela serão executadas em série sem paralelismo.
FeedOptions.PartitionKey QueryRequestOptions.PartitionKey - Comportamento mantido.
FeedOptions.EnableCrossPartitionQuery Removidos. O comportamento padrão no SDK 3.0 é que consultas entre partições serão executadas sem a necessidade de habilitar a propriedade especificamente.
FeedOptions.PopulateQueryMetrics Removidos. Agora está habilitado por padrão e parte do diagnóstico.
FeedOptions.RequestContinuation Removidos. Agora é promovido para os próprios métodos de consulta.
FeedOptions.JsonSerializerSettings Removidos. Consulte como personalizar a serialização para obter informações adicionais.
FeedOptions.PartitionKeyRangeId Removidos. O mesmo resultado pode ser obtido usando FeedRange como entrada para o método de consulta.
FeedOptions.DisableRUPerMinuteUsage Removidos.

Construindo um cliente

O SDK do .NET v3 fornece uma classe fluente CosmosClientBuilder que substitui a necessidade do URI de fábrica do SDK v2.

O design fluente cria URLs internamente e permite que um único Container objeto seja passado em vez de um DocumentClient, DatabaseNamee DocumentCollection.

O exemplo a seguir cria um novo CosmosClientBuilder com um ConsistencyLevel forte e uma lista de locais preferenciais:

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

Exceções

Onde o SDK v2 usado DocumentClientException para sinalizar erros durante as operações, o SDK v3 usa CosmosException, que expõe o StatusCode, Diagnosticse outras informações relacionadas à resposta. Todas as informações completas são serializadas quando ToString() são usadas:

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

Diagnóstico

Onde o SDK v2 tinha diagnósticos somente diretos disponíveis por meio da RequestDiagnosticsString propriedade, o SDK v3 usa Diagnostics disponível em todas as respostas e exceções, que são mais ricas e não se restringem ao modo Direct. Eles incluem não apenas o tempo gasto no SDK para a operação, mas também as regiões contatadas pela operação:

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()
}

Política de conexão

Algumas configurações em ConnectionPolicy foram renomeadas ou substituídas por CosmosClientOptions:

SDK do .NET v2 SDK do .NET v3
EnableEndpointDiscovery LimitToEndpoint - O valor agora está invertido, se EnableEndpointDiscovery estava sendo definido como true, LimitToEndpoint deve ser definido como false. Antes de usar essa configuração, você precisa entender como ela afeta o cliente.
ConnectionProtocol Removidos. O protocolo está vinculado ao Modo, seja Gateway (HTTPS) ou Direct (TCP). O modo direto com protocolo HTTPS não é mais suportado no SDK V3 e a recomendação é usar o protocolo TCP.
MediaRequestTimeout Removidos. Os anexos não são mais suportados.
SetCurrentLocation CosmosClientOptions.ApplicationRegion pode ser usado para obter o mesmo efeito.
PreferredLocations CosmosClientOptions.ApplicationPreferredRegions pode ser usado para obter o mesmo efeito.
UserAgentSuffix CosmosClientBuilder.ApplicationName pode ser usado para obter o mesmo efeito.
UseMultipleWriteLocations Removidos. O SDK deteta automaticamente se a conta oferece suporte a vários pontos de extremidade de gravação.

Política de indexação

Na política de indexação, não é possível configurar essas propriedades. Quando não especificadas, essas propriedades agora sempre terão os seguintes valores:

Nome da propriedade Novo valor (não configurável)
Kind range
dataType String e Number

Consulte esta seção para obter exemplos de políticas de indexação para incluir e excluir caminhos. Devido a melhorias no mecanismo de consulta, a configuração dessas propriedades, mesmo se estiver usando uma versão mais antiga do SDK, não tem impacto no desempenho.

Token de sessão

Onde o SDK v2 expôs o token de sessão de uma resposta como para casos em ResourceResponse.SessionToken que a captura do token de sessão foi necessária, porque o token de sessão é um cabeçalho, o SDK v3 expõe esse valor na Headers.Session propriedade de qualquer resposta.

Carimbo de Data/Hora

Onde o SDK v2 expôs o carimbo de data/hora de um documento por meio da Timestamp propriedade, porque Document não está mais disponível, os usuários podem mapear a propriedade do _tssistema para uma propriedade em seu modelo.

OpenAsync

Para casos de uso em que OpenAsync() estava sendo usado para aquecer o cliente SDK v2, CreateAndInitializeAsync pode ser usado para criar e aquecer um cliente SDK v3.

Usando as APIs do processador de feed de alterações diretamente do SDK v3

O SDK v3 tem suporte interno para as APIs do Change Feed Processor, permitindo que você use o mesmo SDK para criar seu aplicativo e alterar a implementação do processador de feed. Anteriormente, você tinha que usar uma biblioteca separada do processador de feed de alterações.

Para obter mais informações, consulte como migrar da biblioteca do processador de feed de alterações para o SDK do Azure Cosmos DB .NET v3

Alterar consultas de feed

Considera-se que a execução de consultas de feed de alterações no SDK v3 está usando o modelo de pull de feed de alterações. Siga esta tabela para migrar a configuração:

SDK do .NET v2 SDK do .NET v3
ChangeFeedOptions.PartitionKeyRangeId FeedRange - Para obter paralelismo, a leitura da mudança de alimentação pode ser usada FeedRanges . Não é mais um parâmetro necessário, você pode ler o Change Feed para um contêiner inteiro facilmente agora.
ChangeFeedOptions.PartitionKey FeedRange.FromPartitionKey - Um FeedRange representando a Chave de Partição desejada pode ser usado para ler o Feed de Alteração para esse valor de Chave de Partição.
ChangeFeedOptions.RequestContinuation ChangeFeedStartFrom.Continuation - O iterador de alimentação de mudança pode ser interrompido e retomado a qualquer momento, salvando a continuação e usando-a ao criar um novo iterador.
ChangeFeedOptions.StartTime ChangeFeedStartFrom.Time
ChangeFeedOptions.StartFromBeginning ChangeFeedStartFrom.Beginning
ChangeFeedOptions.MaxItemCount ChangeFeedRequestOptions.PageSizeHint - O iterador de alimentação de mudança pode ser interrompido e retomado a qualquer momento, salvando a continuação e usando-a ao criar um novo iterador.
IDocumentQuery.HasMoreResults response.StatusCode == HttpStatusCode.NotModified - O feed de mudanças é conceitualmente infinito, então sempre poderia haver mais resultados. Quando uma resposta contém o código de HttpStatusCode.NotModified status, isso significa que não há novas alterações para ler no momento. Você pode usar isso para parar e salvar a continuação ou para dormir temporariamente ou esperar e, em seguida, ligar ReadNextAsync novamente para testar novas alterações.
Manuseamento de divisões Não é mais necessário que os usuários lidem com exceções divididas ao ler o feed de alterações, as divisões serão tratadas de forma transparente, sem a necessidade de interação do usuário.

Usando a biblioteca de executores em massa diretamente do SDK V3

O SDK v3 tem suporte interno para a biblioteca de executores em massa, permitindo que você use o mesmo SDK para criar seu aplicativo e executar operações em massa. Anteriormente, era necessário usar uma biblioteca de executores em massa separada.

Para obter mais informações, consulte como migrar da biblioteca de executores em massa para suporte em massa no SDK do Azure Cosmos DB .NET V3

Personalizar a serialização

O SDK do .NET V2 permite definir JsonSerializerSettings em RequestOptions no nível operacional usado para desserializar o documento de resultado:

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

O SDK do .NET v3 fornece uma interface de serializador para personalizar totalmente o mecanismo de serialização ou opções de serialização mais genéricas como parte da construção do cliente.

A personalização da serialização no nível de operação pode ser obtida através do uso de APIs de fluxo:

// .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
        }
    }
}

Comparações de trechos de código

O trecho de código a seguir mostra as diferenças em como os recursos são criados entre os SDKs do .NET v2 e v3:

Operações da base de dados

Criar uma base de dados

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

Ler uma base de dados por 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()}");
        }
    }
}

Eliminar uma base de dados

// 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");
        }
    }
}

Operações de contentores

Criar um contêiner (Autoscale + Time to live with expiration)

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

Ler propriedades do contêiner

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

Eliminar um contentor

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

Operações de item e consulta

Criar um item

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

Ler todos os itens em um contêiner

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

Itens de consulta

Alterações no SqlQuerySpec (QueryDefinition no SDK v3.0)

A SqlQuerySpec classe no SDK v2 agora foi renomeada para QueryDefinition no SDK v3.

SqlParameterCollection e SqlParameter foi removido. Os parâmetros agora são adicionados ao QueryDefinition modelo com um construtor usando QueryDefinition.WithParametero . Os usuários podem acessar os parâmetros com 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);
        }
    }
}

Eliminar um item

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

Alterar consulta de feed

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
        }
    }
}

Próximos passos