Tutorial: Entwickeln einer .NET-Konsolenanwendung mit Azure Cosmos DB for NoSQL

GILT FÜR: NoSQL

Mit dem Azure SDK für .NET können Sie Daten zu einer API für NoSQL-Container hinzufügen, und zwar entweder asynchrone einzelne Vorgänge oder einen transaktionalen Batch. In diesem Tutorial erfahren Sie, wie Sie eine neue .NET-Konsolenanwendung erstellen, die einem Container mehrere Elemente hinzufügt.

In diesem Tutorial lernen Sie Folgendes:

  • Erstellen einer Datenbank mithilfe der API für NoSQL
  • Erstellen einer .NET-Konsolenanwendung und Hinzufügen des Azure SDK für .NET
  • Hinzufügen einzelner Elemente zu einem API für NoSQL-Container
  • Effizientes Abrufen von Elementen aus einem API für NoSQL-Container
  • Erstellen einer Transaktion mit Batchänderungen für den API für NoSQL-Container

Voraussetzungen

Erstellen von API für NoSQL-Ressourcen

Erstellen Sie zunächst eine leere Datenbank im vorhandenen API für NoSQL-Konto. Später erstellen Sie mithilfe des Azure SDK für .NET einen Container.

  1. Navigieren Sie im Azure-Portal zu Ihrem vorhandenen API für NoSQL-Konto.

  2. Wählen Sie im Ressourcenmenü die Option Schlüssel aus.

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

  3. Sehen Sie sich auf der Seite Schlüssel die Werte in den Feldern URI und PRIMÄRSCHLÜSSEL an, und notieren Sie sich diese. Diese Werte werden im gesamten Tutorial verwendet.

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

  4. Wählen Sie im Ressourcenmenü Data Explorer aus.

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

  5. Wählen Sie auf der Seite Daten-Explorer in der Befehlsleiste die Option Neue Datenbank aus.

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

  6. Erstellen Sie im Dialogfeld Neue Datenbank einen neuen Container mit den folgenden Einstellungen:

    Wert
    Datenbank-ID cosmicworks
    Typ des Datenbankdurchsatzes Manuell
    Menge des Datenbankdurchsatzes 400

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

  7. Wählen Sie OK aus, um die Datenbank zu erstellen.

Erstellen einer .NET-Konsolenanwendung

Jetzt erstellen Sie eine neue .NET-Konsolenanwendung und importieren das Azure SDK für .NET mithilfe der Microsoft.Azure.Cosmos-Bibliothek aus NuGet.

  1. Öffnen Sie ein Terminal in einem leeren Verzeichnis.

  2. Erstellen Sie eine neue Konsolenanwendung mithilfe der integrierten console-Vorlage.

    dotnet new console --langVersion preview
    
  3. Fügen Sie die Version 3.31.1-preview des Microsoft.Azure.Cosmos-Pakets aus NuGet hinzu.

    dotnet add package Microsoft.Azure.Cosmos --version 3.31.1-preview
    
  4. Fügen Sie außerdem die Vorabversion (prerelease) des System.CommandLine-Pakets aus NuGet hinzu.

    dotnet add package System.CommandLine --prerelease
    
  5. Fügen Sie außerdem das Humanizer-Paket aus NuGet hinzu.

    dotnet add package Humanizer
    
  6. Erstellen Sie das Konsolenanwendungsprojekt.

    dotnet build
    
  7. Öffnen Sie Visual Studio Code, und verwenden Sie den aktuellen Projektordner als Arbeitsbereich.

    Tipp

    Sie können code . im Terminal ausführen, um Visual Studio Code zu öffnen und das Arbeitsverzeichnis automatisch als aktuellen Arbeitsbereich zu öffnen.

  8. Navigieren Sie zur Datei Program.cs, und öffnen Sie sie. Löschen Sie den gesamten vorhandenen Code in der Datei.

  9. Fügen Sie diesen Code in die Datei ein, um mithilfe der System.CommandLine-Bibliothek die Befehlszeile auf zwei Zeichenfolgen zu analysieren, die über die Optionen --first und --last übergeben werden.

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

    Hinweis

    Für dieses Tutorial müssen Sie nicht unbedingt verstehen, wie der Befehlszeilenparser funktioniert. Der Parser verfügt über vier Optionen, die beim Ausführen der Anwendung angegeben werden können. Drei der Optionen sind erforderlich, da sie zum Erstellen der Felder für ID und Partitionsschlüssel verwendet werden.

  10. An diesem Punkt wird das Projekt nicht erstellt, da Sie die statische Methode CosmosHandler.ManageCustomerAsync noch nicht definiert haben.

  11. Speichern Sie die Datei Program.cs.

Hinzufügen von Elementen zu einem Container mithilfe des SDK

Als Nächstes verwenden Sie einzelne Vorgänge, um Elemente zum API für NoSQL-Container hinzuzufügen. In diesem Abschnitt definieren Sie die Methode CosmosHandler.ManageCustomerAsync.

  1. Erstellen Sie eine neue Datei CosmosHandler.cs.

  2. Fügen Sie in der Datei CosmosHandler.cs eine neue using-Direktive für die Namespaces Humanizer und Microsoft.Azure.Cosmos hinzu.

    using Humanizer;
    using Microsoft.Azure.Cosmos;
    
  3. Erstellen Sie eine neue statische Klasse mit dem Namen CosmosHandler.

    public static class CosmosHandler
    { }
    
  4. Um zu überprüfen, ob diese App funktioniert, erstellen Sie eine kurze Implementierung der statischen ManageCustomerAsync-Methode, um die Befehlszeileneingabe zu drucken.

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

  6. Führen Sie die Anwendung im Terminal aus.

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  7. Die Ausgabe des Befehls sollte eine lustige Begrüßung sein.

    Hello Mica Pereira of Washington, United States!
    
  8. Kehren Sie zur Datei CosmosHandler.cs zurück.

  9. Fügen Sie innerhalb der statischen CosmosHandler-Klasse einen neuen private static readonly-Member vom Typ CosmosClient mit dem Namen _client hinzu.

    private static readonly CosmosClient _client;
    
  10. Erstellen Sie einen neuen statischen Konstruktor für die CosmosHandler-Klasse.

    static CosmosHandler()
    { }
    
  11. Erstellen Sie innerhalb des Konstruktors eine neue Instanz der CosmosClient-Klasse, und übergeben Sie zwei Zeichenfolgenparameter mit den Werten für URI und PRIMÄRSCHLÜSSEL, die Sie zuvor im Lab notiert haben. Speichern Sie diese neue Instanz im _client-Member.

    static CosmosHandler()
    {
        _client = new CosmosClient(
            accountEndpoint: "<uri>", 
            authKeyOrResourceToken: "<primary-key>"
        );
    }
    
  12. Erstellen Sie in der statischen CosmosHandler-Klasse eine neue asynchrone Methode namens GetContainerAsync, die einen Container zurückgibt.

    private static async Task<Container> GetContainer()
    { }
    
  13. Fügen Sie für die nächsten Schritte diesen Code in der GetContainerAsync-Methode hinzu.

    1. Rufen Sie die Datenbank cosmicworks ab, und speichern Sie sie in einer Variablen namens database.

      Database database = _client.GetDatabase("cosmicworks");
      
    2. Erstellen Sie eine neue generische List<> von string-Werten in einer Liste von hierarchischen Partitionsschlüsselpfaden, und speichern Sie sie in einer Variablen namens keyPaths.

      List<string> keyPaths = new()
      {
          "/address/country",
          "/address/state"
      };
      
    3. Erstellen Sie eine neue ContainerProperties-Variable mit dem Namen des Containers (customers) und der Liste der Partitionsschlüsselpfade.

      ContainerProperties properties = new(
          id: "customers",
          partitionKeyPaths: keyPaths
      );
      
    4. Verwenden Sie die Methode CreateContainerIfNotExistsAsync, um die Containereigenschaften anzugeben und den Container abzurufen. Wie der Name schon sagt, erstellt diese Methode den Container asynchron, wenn er noch nicht in der Datenbank vorhanden ist. Geben Sie das Ergebnis als Ausgabe der GetContainerAsync-Methode zurück.

      return await database.CreateContainerIfNotExistsAsync(
          containerProperties: properties
      );
      
  14. Löschen Sie den gesamten Code innerhalb der ManageCustomerAsync-Methode.

  15. Fügen Sie für die nächsten Schritte diesen Code in der ManageCustomerAsync-Methode hinzu.

    1. Rufen Sie die GetContainerAsync-Methode asynchron auf, und speichern Sie das Ergebnis in einer Variable namens container.

      Container container = await GetContainerAsync();
      
    2. Erstellen Sie eine neue Variable namens id, die die Kebaberize-Methode von Humanizer verwendet, um den Methodenparameter name zu transformieren.

      string id = name.Kebaberize();
      

      Hinweis

      Die Kebaberize-Methode ersetzt alle Leerzeichen durch Bindestriche und wandelt den Text in Kleinbuchstaben um.

    3. Erstellen Sie ein neues Element vom anonymen Typ mit den Methodenparametern name, stateund country und der Variablen id. Speichern Sie das Element als Variable namens customer.

      var customer = new {
          id = id,
          name = name,
          address = new {
              state = state,
              country = country
          }
      };
      
    4. Verwenden Sie die asynchrone CreateItemAsync-Methode des Containers, um ein neues Element im Container zu erstellen und die HTTP-Antwortmetadaten einer Variablen namens response zuzuweisen.

      var response = await container.CreateItemAsync(customer);
      
    5. Schreiben Sie die Werte der Eigenschaften StatusCode und RequestCharge der response-Variablen in die Konsole. Schreiben Sie auch den Wert der Variablen id.

      Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RUs");
      
  16. Speichern Sie die Datei CosmosHandler.cs.

  17. Führen Sie die Anwendung im Terminal erneut aus.

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  18. Die Ausgabe des Befehls sollte einen Status und eine Anforderungsgebühr für den Vorgang enthalten.

    [Created]       mica-pereira    7.05 RUs
    

    Hinweis

    Die Anforderungsgebühr kann variieren.

  19. Führen Sie die Anwendung noch einmal aus.

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  20. Dieses Mal sollte das Programm abstürzen. Wenn Sie durch die Fehlermeldung scrollen, stellen Sie fest, dass der Absturz durch einen Konflikt im eindeutigen Bezeichner für die Elemente verursacht wurde.

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

Abrufen eines Elements mithilfe des SDK

Nachdem Sie nun das erste Element im Container erstellt haben, können Sie dasselbe SDK zum Abrufen des Elements verwenden. In diesem Abschnitt fragen Sie das Element ab und führen einen Punktlesevorgang durch, um den Unterschied beim Verbrauch von Anforderungseinheiten (RU) zu vergleichen.

  1. Kehren Sie zur Datei CosmosHandler.cs zurück bzw. öffnen Sie diese Datei.

  2. Löschen Sie alle Codezeilen aus der ManageCustomerAsync-Methode mit Ausnahme der ersten beiden Zeilen.

    public static async Task ManageCustomerAsync(string name, string email, string state, string country)
    {
        Container container = await GetContainerAsync();
    
        string id = name.Kebaberize();
    }
    
  3. Fügen Sie für die nächsten Schritte diesen Code in der ManageCustomerAsync-Methode hinzu.

    1. Verwenden Sie die asynchrone CreateItemAsync-Methode des Containers, um ein neues Element im Container zu erstellen und die HTTP-Antwortmetadaten einer Variablen namens response zuzuweisen.

      var response = await container.CreateItemAsync(customer);
      
    2. Erstellen Sie eine neue Zeichenfolge namens sql mit einer SQL-Abfrage, um Elemente abzurufen, auf die ein Filter (@id) zutrifft.

      string sql = """
      SELECT
          *
      FROM customers c
      WHERE c.id = @id
      """;
      
    3. Erstellen Sie eine neue QueryDefinition-Variable namens query, und übergeben Sie die Zeichenfolge sql als einzigen Abfrageparameter. Verwenden Sie außerdem die Fluid-Methode WithParameter, um den Wert der Variablen id auf den Parameter @id anzuwenden.

      var query = new QueryDefinition(
          query: sql
      )
          .WithParameter("@id", id);
      
    4. Verwenden Sie die generische Methode GetItemQueryIterator<> und die Variable query, um einen Iterator zu erstellen, der Daten aus Azure Cosmos DB abruft. Speichern Sie den Iterator in einer Variable namens feed. Schließen Sie diesen gesamten Ausdruck in eine using-Anweisung ein, um den Iterator später zu entfernen.

      using var feed = container.GetItemQueryIterator<dynamic>(
          queryDefinition: query
      );
      
    5. Rufen Sie die ReadNextAsync-Methode der Variablen feed asynchron auf, und speichern Sie das Ergebnis in einer Variable namens response.

      var response = await feed.ReadNextAsync();
      
    6. Schreiben Sie die Werte der Eigenschaften StatusCode und RequestCharge der response-Variablen in die Konsole. Schreiben Sie auch den Wert der Variablen id.

      Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RUs");
      
  4. Speichern Sie die Datei CosmosHandler.cs.

  5. Führen Sie die Anwendung im Terminal aus, um das einzelne Element mithilfe einer SQL-Abfrage zu lesen.

    dotnet run -- --name 'Mica Pereira'
    
  6. Die Ausgabe des Befehls sollte angeben, dass für die Abfrage mehrere RUs erforderlich waren.

    [OK]    mica-pereira    2.82 RUs
    
  7. Löschen Sie in der Datei CosmosHandler.cs erneut alle Codezeilen aus der ManageCustomerAsync-Methode mit Ausnahme der ersten beiden Zeilen.

    public static async Task ManageCustomerAsync(string name, string email, string state, string country)
    {
        Container container = await GetContainerAsync();
    
        string id = name.Kebaberize();
    }
    
  8. Fügen Sie für die nächsten Schritte diesen Code in der ManageCustomerAsync-Methode hinzu.

    1. Erstellen Sie eine neue Instanz von PartitionKeyBuilder, indem Sie die Parameter state und country als mehrteiligen Partitionsschlüsselwert hinzufügen.

      var partitionKey = new PartitionKeyBuilder()
          .Add(country)
          .Add(state)
          .Build();
      
    2. Verwenden Sie die ReadItemAsync<>-Methode des Containers, um einen Punktlesevorgang für das Element im Container mithilfe der Variablen id und partitionKey durchzuführen. Speichern Sie das Ergebnis in einer Variablen namens response.

      var response = await container.ReadItemAsync<dynamic>(
          id: id, 
          partitionKey: partitionKey
      );
      
    3. Schreiben Sie die Werte der Eigenschaften StatusCode und RequestCharge der response-Variablen in die Konsole. Schreiben Sie auch den Wert der Variablen id.

      Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RU");
      
  9. Speichern Sie die Datei CosmosHandler.cs erneut.

  10. Führen Sie die Anwendung noch einmal im Terminal aus, um einen Punktlesevorgang für das einzelne Element durchzuführen.

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  11. Die Ausgabe des Befehls sollte angeben, dass für die Abfrage eine einzelne RU erforderlich war.

    [OK]    mica-pereira    1 RUs
    

Erstellen einer Transaktion mithilfe des SDK

Zum Schluss nehmen Sie das von Ihnen erstellte Element, lesen das Element und erstellen ein anderes zugehöriges Element als Teil einer einzelnen Transaktion mithilfe des Azure SDK für .NET.

  1. Kehren Sie zur Datei CosmosHandler.cs zurück bzw. öffnen Sie diese Datei.

  2. Löschen Sie diese Codezeilen aus der ManageCustomerAsync-Methode.

    var response = await container.ReadItemAsync<dynamic>(
        id: id, 
        partitionKey: partitionKey
    );
    
    Console.WriteLine($"[{response.StatusCode}]\t{id}\t{response.RequestCharge} RUs");
    
  3. Fügen Sie für die nächsten Schritte diesen neuen Code in der ManageCustomerAsync-Methode hinzu.

    1. Erstellen Sie ein neues Element vom anonymen Typ mit den Methodenparametern name, stateund country und der Variablen id. Speichern Sie das Element als Variable namens customerCart. Dieses Element stellt einen Einkaufswagen für den Kunden in Echtzeit dar, der derzeit leer ist.

      var customerCart = new {
          id = $"{Guid.NewGuid()}",
          customerId = id,
          items = new string[] {},
          address = new {
              state = state,
              country = country
          }
      };
      
    2. Erstellen Sie ein weiteres, neues Element vom anonymen Typ mit den Methodenparametern name, stateund country und der Variablen id. Speichern Sie das Element als Variable namens customerCart. Dieses Element stellt Versand- und Kontaktinformationen für den Kunden dar.

      var customerContactInfo = new {
          id = $"{id}-contact",
          customerId = id,
          email = email,
          location = $"{state}, {country}",
          address = new {
              state = state,
              country = country
          }
      };
      
    3. Erstellen Sie einen neuen Batch mithilfe der CreateTransactionalBatch-Methode des Containers, und übergeben Sie die Variable partitionKey. Speichern Sie den Batch in einer Variable namens batch. Verwenden Sie Fluent-Methoden zum Ausführen der folgenden Aktionen:

      Methode Parameter
      ReadItem Zeichenfolgenvariable id
      CreateItem Variable vom anonymen Typ customerCart
      CreateItem Variable vom anonymen Typ customerContactInfo
      var batch = container.CreateTransactionalBatch(partitionKey)
          .ReadItem(id)
          .CreateItem(customerCart)
          .CreateItem(customerContactInfo);
      
    4. Verwenden Sie die ExecuteAsync-Methode des Batchs, um die Transaktion zu starten. Speichern Sie das Ergebnis in einer Variablen namens response.

      using var response = await batch.ExecuteAsync();
      
    5. Schreiben Sie die Werte der Eigenschaften StatusCode und RequestCharge der response-Variablen in die Konsole. Schreiben Sie auch den Wert der Variablen id.

      Console.WriteLine($"[{response.StatusCode}]\t{response.RequestCharge} RUs");
      
  4. Speichern Sie die Datei CosmosHandler.cs erneut.

  5. Führen Sie die Anwendung noch einmal im Terminal aus, um einen Punktlesevorgang für das einzelne Element durchzuführen.

    dotnet run -- --name 'Mica Pereira' --state 'Washington' --country 'United States'
    
  6. Die Ausgabe des Befehls sollte die Anforderungseinheiten anzeigen, die für die gesamte Transaktion verwendet wurden.

    [OK]    16.05 RUs
    

    Hinweis

    Die Anforderungsgebühr kann variieren.

Überprüfen der endgültigen Daten im Daten-Explorer

Zum Abschluss verwenden Sie den Daten-Explorer im Azure-Portal, um die Daten und den Container anzuzeigen, die Sie in diesem Tutorial erstellt haben.

  1. Navigieren Sie im Azure-Portal zu Ihrem vorhandenen API für NoSQL-Konto.

  2. Wählen Sie im Ressourcenmenü Data Explorer aus.

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

  3. Erweitern Sie auf der Seite Daten-Explorer die Datenbank cosmicworks, und wählen Sie dann den Container customers aus.

    Screenshot of the selected container node within the database node.

  4. Wählen Sie in der Befehlsleiste die Option Neue SQL-Abfrage aus.

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

  5. Sehen Sie sich im Abfrage-Editor diese SQL-Abfragezeichenfolge an.

    SELECT * FROM c
    
  6. Wählen Sie Abfrage ausführen aus, um die Abfrage auszuführen, und sehen Sie sich die Ergebnisse an.

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

  7. Die Ergebnisse sollten ein JSON-Array mit drei Elementen enthalten, die in diesem Tutorial erstellt wurden. Beachten Sie, dass alle Elemente denselben hierarchischen Partitionsschlüsselwert, aber eindeutige ID-Felder aufweisen. Die enthaltene Beispielausgabe ist zu Kürzungszwecken abgeschnitten.

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

Bereinigen von Ressourcen

Löschen Sie die in diesem Tutorial verwendete Datenbank, falls Sie sie nicht mehr benötigen. Navigieren Sie dazu zur Kontoseite, wählen Sie Daten-Explorer und dann die Datenbank cosmicworks aus. Wählen Sie schließlich Löschen aus.

Nächste Schritte

Nachdem Sie nun Ihre erste .NET-Konsolenanwendung mithilfe von Azure Cosmos DB erstellt haben, sehen Sie sich das nächste Tutorial an, in dem Sie eine vorhandene Webanwendung für die Verwendung von Azure Cosmos DB-Daten aktualisieren.