Build a product management application - C#

In this exercise, you build a console application that connects to your Azure DocumentDB cluster and performs CRUD operations against the product catalog. You use Visual Studio Code and its integrated terminal to create, edit, and run the application.

Prerequisites

Set up your connection string

Open Visual Studio Code and open a new terminal (Terminal > New Terminal). Set the connection string as an environment variable. Replace the placeholders with your cluster details.

macOS/Linux (bash):

export AZURE_DOCUMENTDB_CONNECTION_STRING="mongodb+srv://<username>:<password>@<cluster-name>.global.mongocluster.cosmos.azure.com/?tls=true&authMechanism=SCRAM-SHA-256&retrywrites=false&maxIdleTimeMS=120000"

Windows (PowerShell):

$env:AZURE_DOCUMENTDB_CONNECTION_STRING = "mongodb+srv://<username>:<password>@<cluster-name>.global.mongocluster.cosmos.azure.com/?tls=true&authMechanism=SCRAM-SHA-256&retrywrites=false&maxIdleTimeMS=120000"

Create the project

In the Visual Studio Code integrated terminal, navigate to a folder where you want to create the project, then create and enter a new project directory:

mkdir product-manager
cd product-manager

Now set up the project.

  1. Create a new .NET console application in the current directory:

    dotnet new console
    
  2. Install the MongoDB driver:

    dotnet add package MongoDB.Driver
    

    [!NOTE] You may see a warning about a vulnerability in the Snappier package (a transitive dependency of MongoDB.Driver). You can safely ignore this warning for this exercise. The MongoDB team tracks this issue in their driver releases.

  3. Open Program.cs in Visual Studio Code:

    code Program.cs
    

    [!NOTE] The file contains a default "Hello World" template generated by dotnet new console. You replace this content in the next step.

Write the application

You build the application incrementally, adding one section at a time so you can run and verify each step before moving on.

Step 1: Connect and verify

Replace the contents of Program.cs with the following code. This code creates a client, verifies the connection, and sets up placeholders for the remaining steps.

using MongoDB.Bson;
using MongoDB.Driver;

var connectionString = Environment.GetEnvironmentVariable("AZURE_DOCUMENTDB_CONNECTION_STRING");
var settings = MongoClientSettings.FromConnectionString(connectionString);
var client = new MongoClient(settings);

// Verify connection
await client.GetDatabase("admin").RunCommandAsync<BsonDocument>(new BsonDocument("ping", 1));
Console.WriteLine("Connected to Azure DocumentDB\n");

var db = client.GetDatabase("cosmicworks");
var products = db.GetCollection<BsonDocument>("products");

// Step 2: Insert three sample products (add code here)

// Step 3: Find the helmet by SKU (add code here)

// Step 4: Query products under $100 (add code here)

// Step 5: Update the helmet inventory and tags (add code here)

// Step 6: Delete the jersey (add code here)

Save the file and run it:

dotnet run

You should see:

Connected to Azure DocumentDB

Step 2: Insert three sample products

Replace the // Step 2 comment with the following code:

// Step 2: Insert three sample products
var sampleProducts = new List<BsonDocument>
{
    new BsonDocument {
        { "sku", "BK-M82S-38" }, { "name", "Mountain-100 Silver, 38" }, { "price", 3399.99 },
        { "category", new BsonDocument("name", "Mountain Bikes") },
        { "tags", new BsonArray { "mountain", "aluminum", "high-performance" } },
        { "inventory", 45 }
    },
    new BsonDocument {
        { "sku", "HL-U509" }, { "name", "Sport-100 Helmet, Black" }, { "price", 34.99 },
        { "category", new BsonDocument("name", "Helmets") },
        { "tags", new BsonArray { "adjustable", "reflective", "lightweight" } },
        { "inventory", 320 }
    },
    new BsonDocument {
        { "sku", "SJ-0194-M" }, { "name", "Short-Sleeve Classic Jersey, M" }, { "price", 53.99 },
        { "category", new BsonDocument("name", "Jerseys") },
        { "tags", new BsonArray { "breathable", "summer" } },
        { "inventory", 185 }
    }
};

await products.DeleteManyAsync(new BsonDocument());  // Clear existing data
await products.InsertManyAsync(sampleProducts);
Console.WriteLine($"Inserted {sampleProducts.Count} products");

Save and run. You should now see:

Connected to Azure DocumentDB

Inserted 3 products

Step 3: Find the helmet by SKU

Replace the // Step 3 comment with the following code:

// Step 3: Find the helmet by SKU
var helmetFilter = Builders<BsonDocument>.Filter.Eq("sku", "HL-U509");
var helmet = await products.Find(helmetFilter).FirstOrDefaultAsync();
Console.WriteLine($"\nFound product: {helmet["name"]}. ${helmet["price"].AsDouble:F2}");

Save and run. The new output line should be:

Found product: Sport-100 Helmet, Black. $34.99

Step 4: Query products under $100

Replace the // Step 4 comment with the following code:

// Step 4: Query products under $100
var priceFilter = Builders<BsonDocument>.Filter.Lt("price", 100);
var affordable = await products.Find(priceFilter).ToListAsync();
Console.WriteLine("\nProducts under $100:");
foreach (var product in affordable)
{
    Console.WriteLine($"  {product["name"]}: ${product["price"].AsDouble:F2}");
}

Save and run. The new output lines should be:

Products under $100:
  Sport-100 Helmet, Black: $34.99
  Short-Sleeve Classic Jersey, M: $53.99

Step 5: Update the helmet inventory and tags

Replace the // Step 5 comment with the following code. This code retrieves the helmet before and after the update so you can compare the changes.

// Step 5: Update the helmet inventory and tags
var before = await products.Find(helmetFilter).FirstOrDefaultAsync();
Console.WriteLine($"\nBefore update - inventory: {before["inventory"]}, tags: {before["tags"]}");

var update = Builders<BsonDocument>.Update
    .Inc("inventory", -5)
    .AddToSet("tags", "popular");
await products.UpdateOneAsync(helmetFilter, update);

var after = await products.Find(helmetFilter).FirstOrDefaultAsync();
Console.WriteLine($"After update  - inventory: {after["inventory"]}, tags: {after["tags"]}");

Save and run. The new output lines should be:

Before update - inventory: 320, tags: [adjustable, reflective, lightweight]
After update  - inventory: 315, tags: [adjustable, reflective, lightweight, popular]

Step 6: Delete the jersey

Replace the // Step 6 comment with the following code. This displays the product count before and after the delete so you can confirm the operation.

// Step 6: Delete the jersey
var countBefore = await products.CountDocumentsAsync(new BsonDocument());
Console.WriteLine($"\nProducts before delete: {countBefore}");

var deleteFilter = Builders<BsonDocument>.Filter.Eq("sku", "SJ-0194-M");
var deleteResult = await products.DeleteOneAsync(deleteFilter);
Console.WriteLine($"Deleted {deleteResult.DeletedCount} product");

var countAfter = await products.CountDocumentsAsync(new BsonDocument());
Console.WriteLine($"Products after delete: {countAfter}");

Save and run. The new output lines should be:

Products before delete: 3
Deleted 1 product
Products after delete: 2

Verify the final output

After completing all six steps, run your application one final time. The complete output should look similar to:

Connected to Azure DocumentDB

Inserted 3 products

Found product: Sport-100 Helmet, Black. $34.99

Products under $100:
  Sport-100 Helmet, Black: $34.99
  Short-Sleeve Classic Jersey, M: $53.99

Before update - inventory: 320, tags: ['adjustable', 'reflective', 'lightweight']
After update  - inventory: 315, tags: ['adjustable', 'reflective', 'lightweight', 'popular']

Products before delete: 3
Deleted 1 product
Products after delete: 2

The output confirms that your application successfully connected to Azure DocumentDB and performed all four CRUD operations: insert, read, update, and delete.

Clean up

To remove the sample data from your cluster, open MongoDB Shell (mongosh) or add the following line to your application and run it one more time:

await db.DropCollectionAsync("products");

If you no longer need the project files, you can also delete the product-manager directory from your machine.

You now have a working application that connects to Azure DocumentDB and performs all four CRUD operations: inserting documents, querying with filters, updating fields with operators like $inc and $addToSet, and deleting by filter. These operations are the same patterns you use to build production applications on Azure DocumentDB, regardless of which programming language you choose.