# Data Operations In Cosmos DB - Part 1

In a [previous article](https://www.azureguru.net/automate-cosmos-db-database-and-container-creation) we explored ways to automate the creation of database and container in Cosmos DB in the console application.

In this article, we will discuss different methods to perform various data operations in a Cosmos DB container.

### Set Up

Lets start by first declaring a record object that defines the properties of the document to be added.

```csharp
    public record ProductRecord(

    string id,
    string ProductName,
    string ProductCategory,
    string ProductRegion,
    int Quantity,
    string[] PastQuantity,
    Suppliers[] Suppliers
);

    public class Suppliers
    {
        public string SupplierName { get; set; }
        public string SupplierCity { get; set; }

    }
```

The object has the following properties :

* `id` &gt;&gt; Unique GUID
    
* `ProductName` &gt;&gt; Name of the product
    
* `ProductCategory` &gt;&gt; Category of the product
    
* `ProductRegion` &gt;&gt; Region of the product. Remember this also is a partition key
    
* `Quantity` &gt;&gt; Given quantity of the product
    
* `PastQuantity` &gt;&gt; Past quantity of the product. It is a collection
    
* `Suppliers` &gt;&gt; Supplier details like Name & City. This property is an array and can have multiple values
    

Note : We will use Transactional batch class to perform multiple entry operations in a single batch and insert two documents in the container through the same batch.

```csharp
  public static async Task<bool> AddNewProducts()
  {
      string id = Guid.NewGuid().ToString();
      string partitionvalue = "region1";
      PartitionKey partitionKey = new(partitionvalue);

      ProductRecord firstitem = new(
          id: id,
          ProductName: "product1",
          Suppliers: new Suppliers[] { new Suppliers { SupplierName = "SupplierForProduct1", SupplierCity = "SupplierCity1" } },
          ProductCategory: "category1",
          ProductRegion: partitionvalue,
          Quantity: 11,
          PastQuantity: new string[] { "5", "2" });

      id = Guid.NewGuid().ToString();
      ProductRecord secondItem = new(
      id: id,
      ProductName: "product2",
      Suppliers: new Suppliers[] { new Suppliers { SupplierName = "SupplierForProduct2", SupplierCity = "SupplierCity2" } },
      ProductCategory: "category2",
      ProductRegion: partitionvalue,
      Quantity: 6,
      PastQuantity: new string[] { "10", "14" });

      TransactionalBatch batch = container.CreateTransactionalBatch(partitionKey)
                                         .CreateItem<ProductRecord>(firstitem)
                                         .CreateItem<ProductRecord>(secondItem);

      using TransactionalBatchResponse response = await batch.ExecuteAsync();

      return response.IsSuccessStatusCode;

  }
```

Lets break down the code :

Auto create the `Guid` which sets the values for id property .The partition is set for region called `region1`. Remember that our partition key is on `ProductRegion`.

```csharp
string id = Guid.NewGuid().ToString();
string partitionvalue = "region1";
PartitionKey partitionKey = new(partitionvalue);
```

Declare a record named `firstitem` and set the properties and assign it to the `ProductRecord` object.

```csharp
ProductRecord firstitem = new(
          id: id,
          ProductName: "product1",
          Suppliers: new Suppliers[] { new Suppliers { SupplierName = "SupplierForProduct1", SupplierCity = "SupplierCity1" } },
          ProductCategory: "category1",
          ProductRegion: partitionvalue,
          Quantity: 11,
          PastQuantity: new string[] { "5", "2" });
```

Declare a second record named `secondItem` and set its properties and assign it to `ProductRecord` object similar to how we did with `firstitem`.

```csharp
      id = Guid.NewGuid().ToString();
      ProductRecord secondItem = new(
      id: id,
      ProductName: "product2",
      Suppliers: new Suppliers[] { new Suppliers { SupplierName = "SupplierForProduct2", SupplierCity = "SupplierCity2" } },
      ProductCategory: "category2",
      ProductRegion: partitionvalue,
      Quantity: 6,
      PastQuantity: new string[] { "10", "14" });
```

Next, create a transaction batch and then assign the two created record items to a single transaction batch called `batch` for inserting into the container.

```csharp
 TransactionalBatch batch = container.CreateTransactionalBatch(partitionKey)
                                         .CreateItem<ProductRecord>(firstitem)
                                         .CreateItem<ProductRecord>(secondItem);
using TransactionalBatchResponse response = await batch.ExecuteAsync();

 return response.IsSuccessStatusCode;
```

Executing the method inserts 2 documents in the container

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724621923181/7f75080f-d2d6-45fb-bd47-806dd68df51b.png align="left")

Will use the id with value : `e7be6237-29f6-4077-84f2-95d6d75c4045` to demonstrate further operations. For that purpose a static string variable called `id` is declared that holds this value .

```csharp
  static string id = "e7be6237-29f6-4077-84f2-95d6d75c4045";
```

### Method that updates a category name :

```csharp
  public static async Task<string> UpdateProductDetails()
  {
      string partitionvalue = "region1";


      PartitionKey partitionKey = new(partitionvalue);
      ItemResponse<ProductRecord> response = await container.PatchItemAsync<ProductRecord>(
       id: "e7be6237-29f6-4077-84f2-95d6d75c4045",
       partitionKey: new PartitionKey(partitionvalue),
       patchOperations: new[] {
          PatchOperation.Replace($"/ProductCategory", "Category2")
       });

      return response.StatusCode.ToString();
  }
```

**Values before and after update :**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724623281699/84546610-df0b-4e9b-a4d4-378e5652056d.png align="center")

### Method that updates supplier name property in the supplier array.

```csharp
 public static async Task<string> UpdateSuppliertDetails()
 {
     string partitionvalue = "region1";

     PartitionKey partitionKey = new(partitionvalue);
     ItemResponse<ProductRecord> response = await container.PatchItemAsync<ProductRecord>(
      id: id,
      partitionKey: new PartitionKey(partitionvalue),
      patchOperations: new[] {
         PatchOperation.Replace($"/Suppliers/0/SupplierName", "SupplierForProductOne")
      });

     return response.StatusCode.ToString();
 }
```

**Values before and after update :**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724623585111/d17780c5-076f-4651-a091-e5cb3039bdea.png align="center")

### Method that adds a new supplier details to the supplier array

```csharp
 public static async Task<string> AddNewSupplierDetails()
 {
     string partitionvalue = "region1";

     PartitionKey partitionKey = new(partitionvalue);

     ItemResponse<ProductRecord> response = await container.PatchItemAsync<ProductRecord>(
      id: id,
      partitionKey: new PartitionKey(partitionvalue),
      patchOperations: new[] {
         PatchOperation.Add("/Suppliers/-",new Suppliers { SupplierName = "SecondSupplierForProductOne", SupplierCity = "SupplierCity2" })
      });

     return response.StatusCode.ToString();
 }
```

**Values before and after the add operation :**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724623997580/385de233-59db-433a-8a56-d8c175bb54fa.png align="center")

### Method that adds a new entry to the `PastQuantity` array

```csharp
   public static async Task<string> AddNewPastQuantity()
   {
       string partitionvalue = "region1";

       PartitionKey partitionKey = new(partitionvalue);
       ItemResponse<ProductRecord> response = await container.PatchItemAsync<ProductRecord>(
        id: id,
        partitionKey: new PartitionKey(partitionvalue),
        patchOperations: new[] {
            PatchOperation.Add($"/PastQuantity/0", "100")
        });

       return response.StatusCode.ToString();
   }
```

**Note** : We define an index position 0 of the array to insert the value in the array.

```csharp
 PatchOperation.Add($"/PastQuantity/0", "100")
```

**Values before and after the add operation :**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724624128022/b6fbaab5-4742-4e97-9932-cfd512809d91.png align="center")

### Update an existing value of `PastQuantity`

```csharp
public static async Task<string> UpdatePastQuantity()
{
    string partitionvalue = "region1";

    PartitionKey partitionKey = new(partitionvalue);
    ItemResponse<ProductRecord> response = await container.PatchItemAsync<ProductRecord>(
     id: id,
     partitionKey: new PartitionKey(partitionvalue),
     patchOperations: new[] {
         PatchOperation.Replace($"/PastQuantity/0", "110")
     });

    return response.StatusCode.ToString();
}
```

**Note** : Similar to the add operation we define an index position 0 of the array to identify the value that needs to be updated.

```csharp
 PatchOperation.Replace($"/PastQuantity/0", "110")
```

`PastQuantity` **value of 100 is updated to 110**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724624645074/55c68965-f936-4c4e-bba1-b77a693b3e94.png align="center")

### Delete the newly added supplier

```csharp
 public static async Task<string> DeleteSupplierDetails()
 {
     string partitionvalue = "region1";

     PartitionKey partitionKey = new(partitionvalue);

     ItemResponse<ProductRecord> response = await container.PatchItemAsync<ProductRecord>(
      id: id,
      partitionKey: new PartitionKey(partitionvalue),
      patchOperations: new[] {
         PatchOperation.Remove("/Suppliers/1")
      });

     return response.StatusCode.ToString();
 }
```

**Note** : We define an index position 1 of the array to identify the value that needs to be deleted.

```csharp
 PatchOperation.Remove("/Suppliers/1")
```

**Pre and post delete**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724624975102/97c6bc2f-c286-4dd8-ac82-0ae39dec7f41.png align="center")

### Delete the newly added `PastQuantity` value of 100

```csharp
  public static async Task<string> DeletePastQuantity()
  {
      string partitionvalue = "region1";

      PartitionKey partitionKey = new(partitionvalue);
      ItemResponse<ProductRecord> response = await container.PatchItemAsync<ProductRecord>(
       id: id,
       partitionKey: new PartitionKey(partitionvalue),
       patchOperations: new[] {
           PatchOperation.Remove($"/PastQuantity/0")
       });

      return response.StatusCode.ToString();
  }
```

**Note** : We define an index position 0 of the array to identify the value that needs to be deleted.

```csharp
 PatchOperation.Remove($"/PastQuantity/0")
```

**Pre and post delete**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1724625242761/a20585e7-4a0c-4b45-b4df-c4ca43ea9c09.png align="center")

### Closing Notes :

In conclusion, we saw how to leverage the full potential of this powerful NoSQL database. Understanding the methods and techniques of the fundamental data operations that were discussed above is crucial. I hope this article has provided valuable insights and practical knowledge to help use Cosmos DB in real life project.

In the [next article](https://www.azureguru.net/data-retrieval-queries-in-cosmos-db) I will continue to delve into the features related to data retrieval in Cosmos DB.

Happy learning !
