Tuesday, 30 May 2023

Access and insert data to Azure Cosmos database using C# console app

In the below code example, I insert datd to Azure Cosmos DB using C# console app. The code read a JSON file and serialize JSON to C# object callled Model and Product.


using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Threading.Tasks;

using System.Text.Json;

using System.IO;

using Microsoft.Azure.Cosmos;

 

namespace AzCosmosDB

{

    internal class Program

    {

        // in prod below variable must be stored in app settings

        private const string EndpointUrl = "https://demo-cosmosdb-retail.documents.azure.com:443/";

        private const string AuthorizationKey = "eKXwigOPIGlu7NHzBEEr1lqc8zRACDbaJ0t9Q==";

        private const string DatabaseName = "Retail";

        private const string ContainerName = "Online";

        private const string PartitionKey = "/Category";

        private const string JsonFilePath = "D:\\Project\\Azure\\AzCosmosDB\\models.json";

 

        static private int amountToInsert;

        static List<Model> models;

        static async Task Main(string[] args)

        {

            try

            {

                // <CreateClient>

                CosmosClient cosmosClient = new CosmosClient(EndpointUrl, AuthorizationKey, new CosmosClientOptions() { AllowBulkExecution = true });

                // </CreateClient>

                // <Initialize>

                Console.WriteLine($"Creating a database if not already exists...");

                Database database = await cosmosClient.CreateDatabaseIfNotExistsAsync(Program.DatabaseName);

 

                // Configure indexing policy to exclude all attributes to maximize RU/s usage

                Console.WriteLine($"Creating a container if not already exists...");

                await database.DefineContainer(Program.ContainerName, PartitionKey)

                        .WithIndexingPolicy()

                            .WithIndexingMode(IndexingMode.Consistent)

                            .WithIncludedPaths()

                                .Attach()

                            .WithExcludedPaths()

                                .Path("/*")

                                .Attach()

                        .Attach()

                    .CreateAsync();

                // </Initialize>

 

                using (StreamReader reader = new StreamReader(File.OpenRead(JsonFilePath)))

                {

                    string json = await reader.ReadToEndAsync();

                    models = JsonSerializer.Deserialize<List<Model>>(json);

                    amountToInsert = models.Count;

                }

 

                // Prepare items for insertion

                Console.WriteLine($"Preparing {amountToInsert} items to insert...");

 

                // Create the list of Tasks

                Console.WriteLine($"Starting...");

                Stopwatch stopwatch = Stopwatch.StartNew();

                // <ConcurrentTasks>

                Container container = database.GetContainer(ContainerName);

 

                List<Task> tasks = new List<Task>(amountToInsert);

                foreach (Model model in models)

                {

                    tasks.Add(container.CreateItemAsync(model, new PartitionKey(model.Category))

                        .ContinueWith(itemResponse =>

                        {

                            if (!itemResponse.IsCompletedSuccessfully)

                            {

                                AggregateException innerExceptions = itemResponse.Exception.Flatten();

                                if (innerExceptions.InnerExceptions.FirstOrDefault(innerEx => innerEx is CosmosException) is CosmosException cosmosException)

                                {

                                    Console.WriteLine($"Received {cosmosException.StatusCode} ({cosmosException.Message}).");

                                }

                                else

                                {

                                    Console.WriteLine($"Exception {innerExceptions.InnerExceptions.FirstOrDefault()}.");

                                }

                            }

                        }));

                }

                // Wait until all are done

                await Task.WhenAll(tasks);

                // </ConcurrentTasks>

                stopwatch.Stop();

 

                Console.WriteLine($"Finished writing {amountToInsert} items in {stopwatch.Elapsed}.");

            }

            catch (Exception ex)

            {

                Console.WriteLine(ex);

            }

        }

    }

    public class Model

        {

            public string id { get; set; }

            public string Name { get; set; }

            public string Category { get; set; }

            public string Description { get; set; }

            public string Photo { get; set; }

            public IList<Product> Products { get; set; }

        }

 

    public class Product

        {

            public string id { get; set; }

            public string Name { get; set; }

            public string Number { get; set; }

            public string Category { get; set; }

            public string Color { get; set; }

            public string Size { get; set; }

            public decimal? Weight { get; set; }

            public decimal ListPrice { get; set; }

            public string Photo { get; set; }

        }

}


JSON Example:

[

  {

    "id": "0481d7e1-4970-4efa-a560-020f6579918d",

    "Name": "LL Fork",

    "Category": "Forks",

    "Description": "Stout design absorbs shock and offers more precise steering.",

    "Products": [

      {

        "id": "fb8502be-07eb-4134-ab06-c3a9959a52ae",

        "Name": "LL Fork",

        "Number": "FK-1639",

        "Category": "Forks",

        "Color": null,

        "Size": null,

        "Weight": null,

        "ListPrice": 148.22,

        "Photo": "fork.jpg"

      }

    ],

    "Photo": "fork.jpg"

  },

  {

    "id": "ca18ecfd-2023-4fa7-a556-0321153bca34",

    "Name": "ML Road Frame-W",

    "Category": "Road Frames",

    "Description": "Made from the same aluminum alloy as our top-of-the line HL frame, the ML features a lightweight down-tube milled to the perfect diameter for optimal strength. Women's version.",

    "Products": [

      {

        "id": "22df26f2-60bc-493e-a14a-5500633e9f7e",

        "Name": "ML Road Frame-W - Yellow, 40",

        "Number": "FR-R72Y-40",

        "Category": "Road Frames",

        "Color": "Yellow",

        "Size": "40",

        "Weight": 1006.97,

        "ListPrice": 594.83,

        "Photo": "no_image_available.jpg"

      },

      {

        "id": "207b54da-5404-415d-8578-9a45082e3bf1",

        "Name": "ML Road Frame-W - Yellow, 42",

        "Number": "FR-R72Y-42",

        "Category": "Road Frames",

        "Color": "Yellow",

        "Size": "42",

        "Weight": 1025.11,

        "ListPrice": 594.83,

        "Photo": "no_image_available.jpg"

      },

      {

        "id": "22976fa7-0ad0-40f9-b4f9-ba10279ea1a3",

        "Name": "ML Road Frame-W - Yellow, 38",

        "Number": "FR-R72Y-38",

        "Category": "Road Frames",

        "Color": "Yellow",

        "Size": "38",

        "Weight": 988.83,

        "ListPrice": 594.83,

        "Photo": "no_image_available.jpg"

      },

      {

        "id": "a0fad492-ac24-4fcf-8d2a-d21d06386ae1",

        "Name": "ML Road Frame-W - Yellow, 44",

        "Number": "FR-R72Y-44",

        "Category": "Road Frames",

        "Color": "Yellow",

        "Size": "44",

        "Weight": 1043.26,

        "ListPrice": 594.83,

        "Photo": "no_image_available.jpg"

      },

      {

        "id": "8487bfe0-2138-471e-9c6d-fdb3a67e7d86",

        "Name": "ML Road Frame-W - Yellow, 48",

        "Number": "FR-R72Y-48",

        "Category": "Road Frames",

        "Color": "Yellow",

        "Size": "48",

        "Weight": 1061.4,

        "ListPrice": 594.83,

        "Photo": "no_image_available.jpg"

      }

    ],

    "Photo": "no_image_available.jpg"

  }

 ]


No comments:

Post a Comment