Esercizio - Creare nuovi elementi

Completato

Ricordare che è possibile creare elementi all'interno del contenitore usando l'SDK di Azure Cosmos DB per .NET. Per questo progetto, il contenitore di prodotti conterrà sia i singoli elementi Product che gli elementi speciali Category per ogni categoria. Ci sono due casi da gestire nell'applicazione:

  • Se una categoria è vuota, è sufficiente creare l'elemento Category singolarmente. Non ci sono elementi Product correlati da creare.
  • Tuttavia, se una categoria include prodotti correlati, si vuole creare contemporaneamente l'elemento di categoria e gli articoli di prodotto correlati.

In questo caso ci sono due requisiti chiave:

  1. Creare un elemento singolarmente come singola operazione
  2. Usare un batch transazionale per creare più elementi correlati

Illustration of icons indicating data being uploaded to the cloud.

Dopo aver completato l'esercizio, il progetto conterrà la logica per creare elementi nel contenitore singolarmente o come batch.

Aggiungere un singolo elemento a un contenitore

In Azure Cosmos DB è possibile creare o sostituire gli elementi in un contenitore oppure eseguirne l'upsert. Per creare un elemento, è necessario che l'elemento abbia un identificatore univoco. Per sostituire un elemento, è necessario che l'elemento esista già. Upsert è il meglio di entrambi i mondi, perché controlla l'identificatore univoco, poi sostituisce o crea l'elemento. Per questo progetto, si vuole eseguire l'app più volte senza errori ed è quindi consigliabile scegliere l'opzione di upsert. Per il primo elemento, verrà creata una categoria che non ha prodotti associati. In questo caso si implementerà un'unica operazione upsert con una categoria creata manualmente.

  1. Aprire di nuovo il file Program.cs.

  2. Creare una nuova istanza di Category denominata goggles con i valori seguenti:

    Proprietà valore
    id ef7fa0f1-0e9d-4435-aaaf-a778179a94ad
    categoryId gear-snow-goggles
    Category goggles = new(
        Id: "ef7fa0f1-0e9d-4435-aaaf-a778179a94ad",
        CategoryId: "gear-snow-goggles"
    );
    
  3. Creare una nuova istanza di PartitionKey usando lo stesso valore della proprietà categoryId per l'istanza di Category creata in precedenza.

    PartitionKey gogglesKey = new("gear-snow-goggles");
    
  4. Usare il metodo UpsertItemAsync per creare o sostituire l'elemento passando un oggetto per l'elemento da creare e un valore di chiave di partizione.

    Category result = await container.UpsertItemAsync(goggles, gogglesKey);
    
  5. Stampare diverse proprietà di result nella console, tra cui l'identificatore univoco dell'elemento e il tipo dell'elemento.

    Console.WriteLine($"[New item created]:\t{result.Id}\t(Type: {result.Type})");
    
  6. Creare una nuova istanza di Category denominata helmets con i valori seguenti:

    Proprietà valore
    id 91f79374-8611-4505-9c28-3bbbf1aa7df7
    categoryId gear-climb-helmets
    Category helmets = new(
        Id: "91f79374-8611-4505-9c28-3bbbf1aa7df7",
        CategoryId: "gear-climb-helmets"
    );
    
  7. Creare una nuova istanza di PartitionKey usando lo stesso valore della proprietà categoryId per l'istanza di Category creata in precedenza.

    PartitionKey helmetsKey = new("gear-climb-helmets");
    
  8. Usare il metodo UpsertItemAsync per creare o sostituire l'elemento. Passare un oggetto per l'elemento da creare e un valore di chiave di partizione. Restituire un oggetto di tipo ItemResponse<T>.

    ItemResponse<Category> response = await container.UpsertItemAsync(helmets, helmetsKey);
    
  9. Stampare diverse proprietà di response nella console, tra cui l'identificatore univoco dell'elemento sottostante, il tipo dell'elemento sottostante e l'addebito della richiesta in unità richiesta (UR).

    Console.WriteLine($"[New item created]:\t{response.Resource.Id}\t(Type: {response.Resource.Type})\t(RUs: {response.RequestCharge})");
    
  10. Salvare il file Program.cs.

Implementare più operazioni come batch transazionale

Considerare ora uno scenario in cui si vogliono creare più prodotti insieme a una categoria. Se i prodotti vengono creati, ma la categoria non esiste, i prodotti non sono utili. La creazione di più elementi è una situazione in cui è possibile usare una transazione per raggruppare più operazioni "punto" in modo che abbiano tutte esito positivo o negativo, come una singola unità coesa. Tornando allo scenario, è necessario creare una categoria per le tende da campeggio con alcuni prodotti di tipo tenda. È già presente un singolo elemento Category senza elementi Product. Ecco quale deve essere il risultato finale:

Diagram of items in Azure Cosmos DB grouped by their partition key.

In questa sezione verrà creato un batch transazionale per creare contemporaneamente la categoria tents e i prodotti correlati.

  1. In Program.cs creare una nuova istanza Category denominata tents con i valori seguenti:

    Proprietà valore
    id 5df21ec5-813c-423e-9ee9-1a2aaead0be4
    categoryId gear-camp-tents
    Category tents = new(
        Id: "5df21ec5-813c-423e-9ee9-1a2aaead0be4",
        CategoryId: "gear-camp-tents"
    );
    
  2. Creare quattro istanze del tipo Product usando i valori seguenti.

    Proprietà cirroa kuloar mammatin nimbolo
    ID e8dddee4-9f43-4d15-9b08-0d7f36adcac8 e6f87b8d-8cd7-4ade-a005-14d3e2fbd1aa f7653468-c4b8-47c9-97ff-451ee55f4fd5 6e3b7275-57d4-4418-914d-14d1baca0979
    CategoryId gear-camp-tents gear-camp-tents gear-camp-tents gear-camp-tents
    Nome Cirroa Tent Kuloar Tent Mammatin Tent Nimbolo Tent
    Price 490.00 530.00 0.00 330.00
    Archived false false true false
    Quantità 15 8 0 35
    Product cirroa = new(
        Id: "e8dddee4-9f43-4d15-9b08-0d7f36adcac8",
        CategoryId: "gear-camp-tents"
    ){
        Name = "Cirroa Tent",
        Price = 490.00m,
        Archived = false,
        Quantity = 15
    };
    
    Product kuloar = new(
        Id: "e6f87b8d-8cd7-4ade-a005-14d3e2fbd1aa",
        CategoryId: "gear-camp-tents"
    ){
        Name = "Kuloar Tent",
        Price = 530.00m,
        Archived = false,
        Quantity = 8
    };
    
    Product mammatin = new(
        Id: "f7653468-c4b8-47c9-97ff-451ee55f4fd5",
        CategoryId: "gear-camp-tents"
    ){
        Name = "Mammatin Tent",
        Price = 0.00m,
        Archived = true,
        Quantity = 0
    };
    
    Product nimbolo = new(
        Id: "6e3b7275-57d4-4418-914d-14d1baca0979",
        CategoryId: "gear-camp-tents"
    ){
        Name = "Nimbolo Tent",
        Price = 330.00m,
        Archived = false,
        Quantity = 35
    };
    
  3. Creare ora una nuova istanza di PartitionKey usando il valore gear-camp-tents.

    PartitionKey tentsKey = new("gear-camp-tents");
    
  4. Creare un nuovo batch transazionale con ambito impostato sul valore della chiave di partizione gear-camp-tents usando il metodo CreateTransactionalBatch(PartitionKey). Usando la sintassi Fluent, aggiungere cinque operazioni upsert per creare gli elementi necessari nel contenitore per la categoria e tutti i prodotti correlati.

    TransactionalBatch batch = container.CreateTransactionalBatch(tentsKey)
        .UpsertItem<Category>(tents)
        .UpsertItem<Product>(cirroa)
        .UpsertItem<Product>(kuloar)
        .UpsertItem<Product>(mammatin)
        .UpsertItem<Product>(nimbolo);
    
  5. Restituire come output un messaggio nella console per indicare che si sta avviando un'operazione batch.

    Console.WriteLine("[Batch started]");
    
  6. Usare il metodo TransactionalBatch.ExecuteAsync per eseguire il batch e restituire un tipo di risposta speciale.

    using TransactionalBatchResponse batchResponse = await batch.ExecuteAsync();
    
  7. Usando un ciclo for, eseguire l'iterazione di tutti gli elementi nella risposta. Prima di tutto, convertire ogni elemento nel tipo TransactionalBatchOperationResult usando la classe di base Item come elemento generico. Stampare quindi l'identificatore univoco e il tipo dell'oggetto response.

    for (int i = 0; i < batchResponse.Count; i++)
    {
        TransactionalBatchOperationResult<Item> batchResult = batchResponse.GetOperationResultAtIndex<Item>(i);
        Console.WriteLine($"[New item created]:\t{batchResult.Resource.Id}\t(Type: {batchResult.Resource.Type})");
    }
    
  8. Restituire come output un altro messaggio nella console per indicare che il batch è stato completato. Includere l'addebito della richiesta per l'intero batch nel messaggio.

    Console.WriteLine($"[Batch completed]:\t(RUs: {batchResponse.RequestCharge})");
    
  9. Salvare il file Program.cs.

Controlla il tuo lavoro

L'app crea ora più elementi ed è progettata per essere sufficientemente resiliente da consentire l'esecuzione più volte senza causare un'eccezione. Eseguire ora l'applicazione e controllare l'output per gli identificatori univoci di ognuno dei sei nuovi elementi creati.

  1. Eseguire l'applicazione .NET nel terminale:

    dotnet run
    
  2. Osservare l'output dell'esecuzione dell'applicazione. L'output dovrebbe essere simile all'esempio seguente:

    ...
    [New item created]:     ef7fa0f1-0e9d-4435-aaaf-a778179a94ad    (Type: Category)
    [New item created]:     91f79374-8611-4505-9c28-3bbbf1aa7df7    (Type: Category)        (RUs: 10.29)
    [Batch started]
    [New item created]:     5df21ec5-813c-423e-9ee9-1a2aaead0be4    (Type: Category)
    [New item created]:     e8dddee4-9f43-4d15-9b08-0d7f36adcac8    (Type: Product)
    [New item created]:     e6f87b8d-8cd7-4ade-a005-14d3e2fbd1aa    (Type: Product)
    [New item created]:     f7653468-c4b8-47c9-97ff-451ee55f4fd5    (Type: Product)
    [New item created]:     6e3b7275-57d4-4418-914d-14d1baca0979    (Type: Product)
    [Batch completed]:      (RUs: 36.76)
    

    Suggerimento

    Le unità richiesta (UR) mostrate nell'output di esempio possono variare rispetto all'output ottenuto.