Esercitazione: Sviluppare un'applicazione console .NET con Azure Cosmos DB per NoSQL

SI APPLICA A: NoSQL

Azure SDK per .NET consente di aggiungere dati a un contenitore API per NoSQL sia singole operazioni asincrone che un batch transazionale. Questa esercitazione illustra il processo di creazione di una nuova applicazione console .NET che aggiunge più elementi a un contenitore.

In questa esercitazione apprenderai a:

  • Creare un database usando l'API per NoSQL
  • Creare un'applicazione console .NET e aggiungere Azure SDK per .NET
  • Aggiungere singoli elementi in un contenitore API per NoSQL
  • Recuperare elementi efficienti da un contenitore API per NoSQL
  • Creare una transazione con modifiche batch per il contenitore API per NoSQL

Prerequisiti

Creare un'API per le risorse NoSQL

Creare prima di tutto un database vuoto nell'account API esistente per NoSQL. Si creerà un contenitore usando Azure SDK per .NET in un secondo momento.

  1. Passare all'account API esistente per NoSQL nel portale di Azure.

  2. Nel menu della risorsa selezionare Chiavi.

    Screenshot of an API for NoSQL account page. The Keys option is highlighted in the resource menu.

  3. Nella pagina Chiavi osservare e registrare il valore dei campi URI e CHIAVE PRIMARIA. Questi valori verranno usati durante l'esercitazione.

    Screenshot of the Keys page with the URI and Primary Key fields highlighted.

  4. Nel menu della risorsa selezionare Esplora dati.

    Screenshot of the Data Explorer option highlighted in the resource menu.

  5. Nella pagina Esplora dati selezionare l'opzione Nuovo database nella barra dei comandi.

    Screenshot of the New Database option in the Data Explorer command bar.

  6. Nella finestra di dialogo Nuovo database creare un nuovo contenitore con le impostazioni seguenti:

    Valore
    ID database cosmicworks
    Tipo di velocità effettiva del database Manualee
    Quantità di velocità effettiva del database 400

    Screenshot of the New Database dialog in the Data Explorer with various values in each field.

  7. Selezionare OK per creare il database.

Creare un'applicazione console .NET

A questo punto si creerà una nuova applicazione console .NET e si importerà Azure SDK per .NET usando la Microsoft.Azure.Cosmos libreria da NuGet.

  1. Aprire un terminale in una directory vuota.

  2. Creare una nuova applicazione console usando il console modello predefinito

    dotnet new console --langVersion preview
    
  3. Aggiungere la versione 3.31.1-preview del Microsoft.Azure.Cosmos pacchetto da NuGet.

    dotnet add package Microsoft.Azure.Cosmos --version 3.31.1-preview
    
  4. Aggiungere anche la versione non definitiva del System.CommandLine pacchetto da NuGet.

    dotnet add package System.CommandLine --prerelease
    
  5. Aggiungere anche il Humanizer pacchetto da NuGet.

    dotnet add package Humanizer
    
  6. Compilare il progetto di applicazione console.

    dotnet build
    
  7. Aprire Visual Studio Code usando la cartella del progetto corrente come area di lavoro.

    Suggerimento

    È possibile eseguire code . nel terminale per aprire Visual Studio Code e aprire automaticamente la directory di lavoro come area di lavoro corrente.

  8. Passare a e aprire il file Program.cs . Eliminare tutto il codice esistente nel file.

  9. Aggiungere questo codice al file per usare la libreria System.CommandLine per analizzare la riga di comando per due stringhe passate tramite le --first opzioni e --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);
    

    Nota

    Per questa esercitazione, non è del tutto importante comprendere il funzionamento del parser della riga di comando. Il parser dispone di quattro opzioni che possono essere specificate quando l'applicazione è in esecuzione. Sono necessarie tre delle opzioni perché verranno usate per costruire i campi ID e chiave di partizione.

  10. A questo punto, il progetto non verrà compilato perché non è ancora stato definito il metodo statico CosmosHandler.ManageCustomerAsync .

  11. Salvare il file Program.cs.

Aggiungere elementi a un contenitore usando l'SDK

Si useranno quindi singole operazioni per aggiungere elementi al contenitore API per NoSQL. In questa sezione si definirà il CosmosHandler.ManageCustomerAsync metodo .

  1. Creare un nuovo file CosmosHandler.cs .

  2. Nel file CosmosHandler.cs aggiungere una nuova direttiva using per gli Humanizer spazi dei nomi e Microsoft.Azure.Cosmos .

    using Humanizer;
    using Microsoft.Azure.Cosmos;
    
  3. Creare una nuova classe statica denominata CosmosHandler.

    public static class CosmosHandler
    { }
    
  4. Solo per convalidare il funzionamento dell'app, creare una breve implementazione del metodo statico ManageCustomerAsync per stampare l'input della riga di comando.

    public static async Task ManageCustomerAsync(string name, string email, string state, string country)
    {
        await Console.Out.WriteLineAsync($"Hello {name} of {state}, {country}!");
    }
    
  5. Salvare il file CosmosHandler.cs .

  6. Tornare al terminale ed eseguire l'applicazione.

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  7. L'output del comando deve essere un messaggio di saluto divertente.

    Hello Mica Pereira of Washington, United States!
    
  8. Tornare al file CosmosHandler.cs .

  9. All'interno della classe static CosmosHandler aggiungere un nuovo private static readonly membro di tipo CosmosClient denominato _client.

    private static readonly CosmosClient _client;
    
  10. Creare un nuovo costruttore statico per la CosmosHandler classe .

    static CosmosHandler()
    { }
    
  11. All'interno del costruttore creare una nuova istanza della CosmosClient classe passando due parametri stringa con i valori URI e PRIMARY KEY registrati in precedenza nel lab. Archiviare questa nuova istanza nel _client membro.

    static CosmosHandler()
    {
        _client = new CosmosClient(
            accountEndpoint: "<uri>", 
            authKeyOrResourceToken: "<primary-key>"
        );
    }
    
  12. Tornare all'interno della classe static CosmosHandler , creare un nuovo metodo asincrono denominato GetContainerAsync che restituisce un oggetto Container.

    private static async Task<Container> GetContainer()
    { }
    
  13. Per i passaggi successivi, aggiungere questo codice all'interno del GetContainerAsync metodo .

    1. Ottenere il cosmicworks database e archiviarlo in una variabile denominata database.

      Database database = _client.GetDatabase("cosmicworks");
      
    2. Creare un nuovo generico List<> di valori all'interno di string un elenco di percorsi di chiave di partizione gerarchici e archiviarli in una variabile denominata keyPaths.

      List<string> keyPaths = new()
      {
          "/address/country",
          "/address/state"
      };
      
    3. Creare una nuova ContainerProperties variabile con il nome del contenitore (customers) e l'elenco dei percorsi delle chiavi di partizione.

      ContainerProperties properties = new(
          id: "customers",
          partitionKeyPaths: keyPaths
      );
      
    4. Usare il CreateContainerIfNotExistsAsync metodo per fornire le proprietà del contenitore e recuperare il contenitore. Questo metodo creerà in modo asincrono il contenitore se non esiste già all'interno del database. Restituisce il risultato come output del GetContainerAsync metodo .

      return await database.CreateContainerIfNotExistsAsync(
          containerProperties: properties
      );
      
  14. Eliminare tutto il codice all'interno del ManageCustomerAsync metodo .

  15. Per i passaggi successivi, aggiungere questo codice all'interno del ManageCustomerAsync metodo .

    1. Chiamare in modo asincrono il GetContainerAsync metodo e archiviare il risultato in una variabile denominata container.

      Container container = await GetContainerAsync();
      
    2. Creare una nuova variabile denominata id che usa il Kebaberize metodo di Humanizer per trasformare il parametro del name metodo.

      string id = name.Kebaberize();
      

      Nota

      Il Kebaberize metodo sostituirà tutti gli spazi con trattini e converrà il testo in lettere minuscole.

    3. Creare un nuovo elemento tipizzato anonimo usando i nameparametri del metodo , statee country e la id variabile . Archiviare l'elemento come variabile denominata customer.

      var customer = new {
          id = id,
          name = name,
          address = new {
              state = state,
              country = country
          }
      };
      
    4. Usare il metodo asincrono CreateItemAsync del contenitore per creare un nuovo elemento nel contenitore e assegnare i metadati della risposta HTTP a una variabile denominata response.

      var response = await container.CreateItemAsync(customer);
      
    5. Scrivere i valori delle proprietà e RequestCharge della responseStatusCode variabile nella console. Scrivere anche il valore della id variabile.

      Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RUs");
      
  16. Salvare il file CosmosHandler.cs .

  17. Tornare al terminale, eseguire di nuovo l'applicazione.

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  18. L'output del comando deve includere uno stato e un addebito per la richiesta per l'operazione.

    [Created]       mica-pereira    7.05 RUs
    

    Nota

    L'addebito della richiesta può variare.

  19. Eseguire l'applicazione ancora una volta.

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  20. Questa volta, il programma dovrebbe arrestarsi in modo anomalo. Se si scorre il messaggio di errore, si noterà che si è verificato l'arresto anomalo a causa di un conflitto nell'identificatore univoco per gli elementi.

    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."
        ]
    );
    

Recuperare un elemento usando l'SDK

Dopo aver creato il primo elemento nel contenitore, è possibile usare lo stesso SDK per recuperare l'elemento. In questo caso, si eseguirà una query e si leggerà l'elemento per confrontare la differenza nel consumo di unità richiesta (UR).

  1. Tornare o aprire il file CosmosHandler.cs .

  2. Eliminare tutte le righe di codice dal ManageCustomerAsync metodo ad eccezione delle prime due righe.

    public static async Task ManageCustomerAsync(string name, string email, string state, string country)
    {
        Container container = await GetContainerAsync();
    
        string id = name.Kebaberize();
    }
    
  3. Per i passaggi successivi, aggiungere questo codice all'interno del ManageCustomerAsync metodo .

    1. Usare il metodo asincrono CreateItemAsync del contenitore per creare un nuovo elemento nel contenitore e assegnare i metadati della risposta HTTP a una variabile denominata response.

      var response = await container.CreateItemAsync(customer);
      
    2. Creare una nuova stringa denominata sql con una query SQL per recuperare gli elementi in cui corrisponde un filtro (@id).

      string sql = """
      SELECT
          *
      FROM customers c
      WHERE c.id = @id
      """;
      
    3. Creare una nuova QueryDefinition variabile denominata query passando la sql stringa come unico parametro di query. Usare anche il WithParameter metodo fluido per applicare il valore della variabile id al @id parametro .

      var query = new QueryDefinition(
          query: sql
      )
          .WithParameter("@id", id);
      
    4. Usare il GetItemQueryIterator<> metodo generico e la query variabile per creare un iteratore che ottiene i dati da Azure Cosmos DB. Archiviare l'iteratore in una variabile denominata feed. Eseguire il wrapping di questa intera espressione in un'istruzione using per eliminare l'iteratore in un secondo momento.

      using var feed = container.GetItemQueryIterator<dynamic>(
          queryDefinition: query
      );
      
    5. Chiamare in modo asincrono il ReadNextAsync metodo della feed variabile e archiviare il risultato in una variabile denominata response.

      var response = await feed.ReadNextAsync();
      
    6. Scrivere i valori delle proprietà e RequestCharge della responseStatusCode variabile nella console. Scrivere anche il valore della id variabile.

      Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RUs");
      
  4. Salvare il file CosmosHandler.cs .

  5. Tornando al terminale, eseguire l'applicazione per leggere il singolo elemento usando una query SQL.

    dotnet run -- --name 'Mica Pereira'
    
  6. L'output del comando deve indicare che la query richiedeva più UR.

    [OK]    mica-pereira    2.82 RUs
    
  7. Tornare al file CosmosHandler.cs , eliminare di nuovo tutte le righe di codice dal ManageCustomerAsync metodo ad eccezione delle prime due righe.

    public static async Task ManageCustomerAsync(string name, string email, string state, string country)
    {
        Container container = await GetContainerAsync();
    
        string id = name.Kebaberize();
    }
    
  8. Per i passaggi successivi, aggiungere questo codice all'interno del ManageCustomerAsync metodo .

    1. Creare una nuova istanza di aggiungendo i state parametri e country come valore della chiave di PartitionKeyBuilder partizione in più parti.

      var partitionKey = new PartitionKeyBuilder()
          .Add(country)
          .Add(state)
          .Build();
      
    2. Usare il metodo del ReadItemAsync<> contenitore per puntare a leggere l'elemento dal contenitore usando le id variabili e partitionKey . Salvare il risultato in una variabile denominata response.

      var response = await container.ReadItemAsync<dynamic>(
          id: id, 
          partitionKey: partitionKey
      );
      
    3. Scrivere i valori delle proprietà e RequestCharge della responseStatusCode variabile nella console. Scrivere anche il valore della id variabile.

      Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RU");
      
  9. Salvare di nuovo il file CosmosHandler.cs .

  10. Tornare al terminale, eseguire l'applicazione ancora una volta per puntare a leggere il singolo elemento.

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  11. L'output del comando deve indicare che la query richiede una singola UR.

    [OK]    mica-pereira    1 RUs
    

Creare una transazione usando l'SDK

Infine, si userà l'elemento creato, si leggerà l'elemento e si creerà un elemento correlato diverso come parte di una singola transazione usando Azure SDK per .NET.

  1. Tornare o aprire il file CosmosHandler.cs .

  2. Eliminare queste righe di codice dal ManageCustomerAsync metodo .

    var response = await container.ReadItemAsync<dynamic>(
        id: id, 
        partitionKey: partitionKey
    );
    
    Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RUs");
    
  3. Per i passaggi successivi, aggiungere questo nuovo codice all'interno del ManageCustomerAsync metodo .

    1. Creare un nuovo elemento tipizzato anonimo usando i nameparametri del metodo , statee country e la id variabile . Archiviare l'elemento come variabile denominata customerCart. Questo articolo rappresenterà un carrello acquisti in tempo reale per il cliente attualmente vuoto.

      var customerCart = new {
          id = $"{Guid.NewGuid()}",
          customerId = id,
          items = new string[] {},
          address = new {
              state = state,
              country = country
          }
      };
      
    2. Creare un altro nuovo elemento tipizzato anonimo usando i nameparametri del metodo , statee country e la id variabile . Archiviare l'elemento come variabile denominata customerCart. Questo articolo rappresenterà le informazioni di spedizione e contatto per il cliente.

      var customerContactInfo = new {
          id = $"{id}-contact",
          customerId = id,
          email = email,
          location = $"{state}, {country}",
          address = new {
              state = state,
              country = country
          }
      };
      
    3. Creare un nuovo batch usando il metodo del CreateTransactionalBatch contenitore passando la partitionKey variabile. Archiviare il batch in una variabile denominata batch. Usare i metodi Fluent per eseguire le azioni seguenti:

      metodo Parametro
      ReadItem id variabile stringa
      CreateItem customerCart variabile di tipo anonimo
      CreateItem customerContactInfo variabile di tipo anonimo
      var batch = container.CreateTransactionalBatch(partitionKey)
          .ReadItem(id)
          .CreateItem(customerCart)
          .CreateItem(customerContactInfo);
      
    4. Usare il metodo del ExecuteAsync batch per avviare la transazione. Salvare il risultato in una variabile denominata response.

      using var response = await batch.ExecuteAsync();
      
    5. Scrivere i valori delle proprietà e RequestCharge della responseStatusCode variabile nella console. Scrivere anche il valore della id variabile.

      Console.WriteLine($"[{response.StatusCode}]\t{response.RequestCharge} RUs");
      
  4. Salvare di nuovo il file CosmosHandler.cs .

  5. Tornare al terminale, eseguire l'applicazione ancora una volta per puntare a leggere il singolo elemento.

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  6. L'output del comando deve mostrare le unità richiesta usate per l'intera transazione.

    [OK]    16.05 RUs
    

    Nota

    L'addebito della richiesta può variare.

Convalidare i dati finali nel Esplora dati

Per concludere, si userà il Esplora dati nella portale di Azure per visualizzare i dati e il contenitore creati in questa esercitazione.

  1. Passare all'account API esistente per NoSQL nel portale di Azure.

  2. Nel menu della risorsa selezionare Esplora dati.

    Screenshot of the Data Explorer option highlighted in the resource menu.

  3. Nella pagina Esplora dati espandere il cosmicworks database e quindi selezionare il customers contenitore.

    Screenshot of the selected container node within the database node.

  4. Nella barra dei comandi selezionare Nuova query SQL.

    Screenshot of the New SQL Query option in the Data Explorer command bar.

  5. Nell'editor di query osservare questa stringa di query SQL.

    SELECT * FROM c
    
  6. Selezionare Esegui query per eseguire la query e osservare i risultati.

    Screenshot of the Execute Query option in the Data Explorer command bar.

  7. I risultati devono includere una matrice JSON con tre elementi creati in questa esercitazione. Si noti che tutti gli elementi hanno lo stesso valore di chiave di partizione gerarchica, ma campi ID univoci. L'output di esempio incluso viene troncato per brevità.

    [
      {
        "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"
        },
        ...
      }
    ]
    

Pulire le risorse

Quando non è più necessario, eliminare il database usato in questa esercitazione. A tale scopo, passare alla pagina account, selezionare Esplora dati, selezionare il cosmicworks database e quindi selezionare Elimina.

Passaggi successivi

Dopo aver creato la prima applicazione console .NET con Azure Cosmos DB, provare l'esercitazione successiva in cui si aggiornerà un'applicazione Web esistente per usare i dati di Azure Cosmos DB.