Home / Nieuws / Azure Cosmos Database CRUD Operations met C#
23 juni 2022
Door: Sunita Kawale

Azure Cosmos Database CRUD Operations met C#

Uitgelichte afbeelding voor een blog over Azure Cosmos Database

Crud operations in Azure Cosmos Database

In deze blog zullen we leren om Azure Cosmos Database CRUD (Create, Update, Read, Delete) Operations te creëren in de werknemer management webapplicatie (C#).

Voordat we de applicatie starten, moeten we weten: waarom de Azure Cosmos database?

NoSQL – Azure Cosmos DB ondersteunt NoSQL database, wat het een gemakkelijke en moderne manier maakt voor development.
Minder structureren – We kunnen de verschillende soorten gegevens opslaan in een database container.

Snelheid – Met zeer lage latency en hoge beschikbaarheid geeft Microsoft een goede SLA (Service Level Agreement) voor de Cosmos DB.

Throughput – Zeer hoge throughput op alle schalen, en de garantie van beschikbaarheid is 99,999%.

Volledig beheerd – Net als bij andere diensten van Azure hoeven we geen onderhoud te plegen zoals het toepassen van patches of updates, dus er is minder administratief werk.

Gebruik – Tegenwoordig kunnen we deze dienst gebruiken in bijna alle soorten applicaties zoals web, mobiel, gaming, IoT en Telematica, Retail en marketing.

 

Hieronder staan de stappen om een C# webapplicatie te maken.

1. Maak een voorbeeld-webapplicatie met de naam AppCosmosDBCurdOperations.

2. Voeg een nieuwe mapnaam toe als Models en een class Employee. cs zoals de onderstaande code:

3. Voeg een nieuwe map toe met de naam Services, en voeg een Interface toe met de naam ICosmosDbServices.cs. Hieronder staat een voorbeeld-code.

{
        Task<IEnumerable<Employee>> GetItemsAsync(string query);
        Task<Employee> GetItemAsync(string id);
        Task AddItemAsync(Employee item);
        Task UpdateItemAsync(string id, Employee item);
        Task DeleteItemAsync(string id);
    }

4. Maak de nieuwe class CosmosDbService.cs en implementeer de interface.

public class CosmosDbService : ICosmosDbService
{
private Container _container;
 
public CosmosDbService(
CosmosClient dbClient,
string databaseName,
string containerName)
{
this._container = dbClient.GetContainer(databaseName, containerName);
}
 
public async Task AddItemAsync(Employee item)
{
await this._container.CreateItemAsync<Employee>(item, new PartitionKey(item.Id));
}
 
public async Task DeleteItemAsync(string id)
{
await this._container.DeleteItemAsync<Employee>(id, new PartitionKey(id));
 
}
 
public async Task<Employee> GetItemAsync(string id)
{
try
{
ItemResponse<Employee> response = await this._container.ReadItemAsync<Employee>(id, new PartitionKey(id));
return response.Resource;
}
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return null;
}
 
}
 
public async Task<IEnumerable<Employee>> GetItemsAsync(string queryString)
{
var query = this._container.GetItemQueryIterator<Employee>(new QueryDefinition(queryString));
List<Employee> results = new List<Employee>();
while (query.HasMoreResults)
{
var response = await query.ReadNextAsync();
 
results.AddRange(response.ToList());
}
 
return results;
}
 
public async Task UpdateItemAsync(string id, Employee item)
{
await this._container.UpsertItemAsync<Employee>(item, new PartitionKey(id));
}
 
 
}

5. Installeer de vereiste NuGet-pakketten Azure.Cosmos en Microsoft.EntityFrameworkCore.

6. Update het Startup.cs-bestand met de onderstaande code.

public Startup(IConfiguration configuration)

{

Configuration = configuration;

}

 

public IConfiguration Configuration { get; }

 

// This method gets called by the runtime. Use this method to add services to the container.

public void ConfigureServices(IServiceCollection services)

{

services.AddRazorPages();

services.AddSingleton<ICosmosDbService>(InitializeCosmosClientInstanceAsync(Configuration.GetSection(“CosmosDb”)).GetAwaiter().GetResult());

}

 

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

{

if (env.IsDevelopment())

{

app.UseDeveloperExceptionPage();

}

else

{

app.UseExceptionHandler(“/Error”);

// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.

app.UseHsts();

}

 

app.UseHttpsRedirection();

app.UseStaticFiles();

 

app.UseRouting();

 

app.UseAuthorization();

 

app.UseEndpoints(endpoints =>

{

endpoints.MapRazorPages();

});

}

 

/// <summary>

/// Creates a Cosmos DB database and a container with the specified partition key.

/// </summary>

/// <returns></returns>

private static async Task<CosmosDbService> InitializeCosmosClientInstanceAsync(IConfigurationSection configurationSection)

{

string databaseName = configurationSection.GetSection(“DatabaseName”).Value;

string containerName = configurationSection.GetSection(“ContainerName”).Value;

string account = configurationSection.GetSection(“Account”).Value;

string key = configurationSection.GetSection(“Key”).Value;

Microsoft.Azure.Cosmos.CosmosClient client = new Microsoft.Azure.Cosmos.CosmosClient(account, key);

CosmosDbService cosmosDbService = new CosmosDbService(client, databaseName, containerName);

Microsoft.Azure.Cosmos.DatabaseResponse database = await client.CreateDatabaseIfNotExistsAsync(databaseName);

await database.Database.CreateContainerIfNotExistsAsync(containerName, “/id”);

 

return cosmosDbService;

}

7. Voeg de vereiste configuraties toe in AppSettings.json bestanden zoals hieronder.

“CosmosDb”: {

    “Account”: “https://XXXXXXXXXXXX.documents.azure.com:443/”,

    “Key”: “xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”,

    “DatabaseName”: “employeemanagement”,

    “ContainerName”: “empcontainer”

  }

8. Volgens het SOLID principe is het goed om het service gedeelte en het front-end gedeelte te scheiden, maar dit is de demo applicatie dus we zullen het front-end gedeelte in dezelfde applicatie maken. Dus, laten we de map maken binnen de paginamap met de naam Employee en voeg drie Razor pagina’s toe zoals hieronder:

ListEmployee.cshtml, RegisterEmployee.cshtml, UpdateEmployee.cshtml

 

  • ListEmployee.cshtml:
@page

@model AppCosmosDBCurdOperations.Pages.Employees.ListEmployeeModel

 

@{

    ViewData[“Title”] = “ListEmployee”;

}

 

<h4>All Employees</h4>

 

<table class=”table”>

    <thead>

        <tr>

            <th>

                @Html.DisplayNameFor(model => model.Employee[0].Name)

            </th>

            <th>

                @Html.DisplayNameFor(model => model.Employee[0].Email)

            </th>

            <th>

                @Html.DisplayNameFor(model => model.Employee[0].DoB)

            </th>

            <th>

                @Html.DisplayNameFor(model => model.Employee[0].Status)

            </th>

            <th></th>

        </tr>

    </thead>

    <tbody>

        @if (Model.Employee == null) { return; }

        @foreach (var item in Model.Employee)

        {

            <tr>

                <td>

                    @Html.DisplayFor(modelItem => item.Name)

                </td>

                <td>

                    @Html.DisplayFor(modelItem => item.Email)

                </td>

                <td>

                    @Html.DisplayFor(modelItem => item.DoB)

                </td>

                <td>

                    @Html.DisplayFor(modelItem => item.Status)

                </td>

               

                <td>

                    <form method=”post”>

                        <button asp-page-handler=”EditEmployee” asp-route-id=”@item.Id” class=”btn btn-default bi bi-pencil”></button> |

                        <button class=”btn btn-default bi bi-trash” asp-page-handler=”DeleteEmployee” asp-route-id=”@item.Id”></button>

                    </form>

                </td>

            </tr>

        }

    </tbody>

</table>
  • ListEmployee.cshtml.cs:
using AppCosmosDBCurdOperations.Models;

using AppCosmosDBCurdOperations.Services;

using Microsoft.AspNetCore.Mvc;

using Microsoft.AspNetCore.Mvc.RazorPages;

using System.Collections.Generic;

using System.Linq;

using System.Threading.Tasks;

 

namespace AppCosmosDBCurdOperations.Pages.Employees

{

    public class ListEmployeeModel : PageModel

    {

        private readonly ICosmosDbService _cosmosDbService;

        public ListEmployeeModel(ICosmosDbService cosmosDbService)

        {

            _cosmosDbService = cosmosDbService;

        }

 

        public IList<Employee> Employee { get; set; }

 

        public async Task OnGetAsync()

        {

            await GetAllEmployees();

        }

 

        private async Task GetAllEmployees()

        {

            var lstEmployee = await _cosmosDbService.GetItemsAsync(“select * from c”);

            Employee = lstEmployee.ToList();

        }

 

        public async Task OnPostDeleteEmployee(string id)

        {

            await _cosmosDbService.DeleteItemAsync(id);

            await GetAllEmployees();

        }

 

        public IActionResult OnPostEditEmployee(string id)

        {

            return Redirect(“/Employees/UpdateEmployee?id=” + id);

        }

    }

}
  • RegisterEmployee.cshtml:
@page

@model AppCosmosDBCurdOperations.Pages.Employees.RegisterEmployeeModel

 

@{

ViewData[“Title”] = “RegisterEmployee”;

}

 

<h4>Register Employee</h4>

 

 

<hr />

<div class=”row”>

<div class=”col-md-4″>

<form method=”post”>

<div asp-validation-summary=”ModelOnly” class=”text-danger”></div>

 

<div class=”form-group”>

<label asp-for=”Employee.Name” class=”control-label”></label>

<input asp-for=”Employee.Name” class=”form-control” />

<span asp-validation-for=”Employee.Name” class=”text-danger”></span>

</div>

<div class=”form-group”>

<label asp-for=”Employee.Email” class=”control-label”></label>

<input asp-for=”Employee.Email” class=”form-control” />

<span asp-validation-for=”Employee.Email” class=”text-danger”></span>

</div>

<div class=”form-group”>

<label asp-for=”Employee.DoB” class=”control-label”></label>

<input asp-for=”Employee.DoB” class=”form-control”  />

<span asp-validation-for=”Employee.DoB” class=”text-danger”></span>

</div>

<div class=”form-group”>

<label asp-for=”Employee.Status” class=”control-label”></label>

<select asp-for=”Employee.Status” class=”form-control”>

@foreach (var _status in Enum.GetValues(typeof(Models.EmployeeStatus)))

{

<option value=”@_status”>@_status</option>

}

</select>

<span asp-validation-for=”Employee.Status” class=”text-danger”></span>

</div>

<div class=”form-group”>

<input type=”submit” value=”Create” class=”btn btn-primary” />

</div>

</form>

</div>

</div>

@section Scripts {

@{await Html.RenderPartialAsync(“_ValidationScriptsPartial”);}

}
  • RegisterEmployee.cshtml.cs:
using AppCosmosDBCurdOperations.Models;

using AppCosmosDBCurdOperations.Services;

using Microsoft.AspNetCore.Mvc;

using Microsoft.AspNetCore.Mvc.RazorPages;

using System;

using System.Threading.Tasks;

 

namespace AppCosmosDBCurdOperations.Pages.Employees

{

    public class RegisterEmployeeModel : PageModel

    {

        private readonly ICosmosDbService _cosmosDbService;

        public RegisterEmployeeModel(ICosmosDbService cosmosDbService)

        {

            _cosmosDbService = cosmosDbService;

        }

 

        public IActionResult OnGet()

        {

            return Page();

        }

 

        [BindProperty]

        public Employee Employee { get; set; }

 

        // To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD

        public async Task<IActionResult> OnPostAsync()

        {

            if (!ModelState.IsValid)

            {

                return Page();

            }

 

            Employee.Id = Guid.NewGuid().ToString();

            await _cosmosDbService.AddItemAsync(Employee);

            

            return RedirectToPage(“/Employees/ListEmployee”);

        }

    }

}
  • UpdateEmployee.cshtml:
@page

@model AppCosmosDBCurdOperations.Pages.Employees.UpdateEmployeeModel

 

@{

    ViewData[“Title”] = “UpdateEmployee”;

}

 

<h4>Update Employee</h4>

 

 

<hr />

<div class=”row”>

    <div class=”col-md-4″>

        <form method=”post”>

            <div asp-validation-summary=”ModelOnly” class=”text-danger”></div>

            <input type=”hidden” asp-for=”Employee.Id” />

            <div class=”form-group”>

                <label asp-for=”Employee.Name” class=”control-label”></label>

                <input asp-for=”Employee.Name” class=”form-control” />

                <span asp-validation-for=”Employee.Name” class=”text-danger”></span>

            </div>

            <div class=”form-group”>

                <label asp-for=”Employee.Email” class=”control-label”></label>

                <input asp-for=”Employee.Email” class=”form-control” />

                <span asp-validation-for=”Employee.Email” class=”text-danger”></span>

            </div>

            <div class=”form-group”>

                <label asp-for=”Employee.DoB” class=”control-label”></label>

                <input asp-for=”Employee.DoB” class=”form-control” />

                <span asp-validation-for=”Employee.DoB” class=”text-danger”></span>

            </div>

            <div class=”form-group”>

                <label asp-for=”Employee.Status” class=”control-label”></label>

                <select asp-for=”Employee.Status” class=”form-control”>

                    @foreach (var _status in Enum.GetValues(typeof(Models.EmployeeStatus)))

                    {

                        <option value=”@_status”>@_status</option>

                    }

                </select>

                <span asp-validation-for=”Employee.Status” class=”text-danger”></span>

            </div>

            <div class=”form-group”>

                <input type=”submit” value=”Save” class=”btn btn-primary” />

            </div>

        </form>

    </div>

</div>

 

@section Scripts {

    @{await Html.RenderPartialAsync(“_ValidationScriptsPartial”);}

}
  • UpdateEmployee.cshtml.cs:
using AppCosmosDBCurdOperations.Models;

using AppCosmosDBCurdOperations.Services;

using Microsoft.AspNetCore.Mvc;

using Microsoft.AspNetCore.Mvc.RazorPages;

using Microsoft.EntityFrameworkCore;

using System.Threading.Tasks;

 

namespace AppCosmosDBCurdOperations.Pages.Employees

{

    public class UpdateEmployeeModel : PageModel

    {

 

        private readonly ICosmosDbService _cosmosDbService;

        public UpdateEmployeeModel( ICosmosDbService cosmosDbService)

        {

            _cosmosDbService = cosmosDbService;

        }

       

 

        [BindProperty]

        public Employee Employee { get; set; }

 

        public async Task<IActionResult> OnGetAsync(string id)

        {

            if (id == null)

            {

                return NotFound();

            }

 

            Employee = await _cosmosDbService.GetItemAsync(id);

 

            if (Employee == null)

            {

                return NotFound();

            }

            return Page();

        }

 

        // To protect from overposting attacks, enable the specific properties you want to bind to.

        // For more details, see https://aka.ms/RazorPagesCRUD.

        public async Task<IActionResult> OnPostAsync()

        {

            if (!ModelState.IsValid)

            {

                return Page();

            }

 

            try

            {

                await _cosmosDbService.UpdateItemAsync(Employee.Id, Employee);

            }

            catch (DbUpdateConcurrencyException)

            {

                if (!EmployeeExists(Employee.Id))

                {

                    return NotFound();

                }

                else

                {

                    throw;

                }

            }

 

            return RedirectToPage(“/Employees/ListEmployee”);

        }

 

        private bool EmployeeExists(string id)

        {

            var emp = _cosmosDbService.GetItemAsync(id);

            return emp != null;

        }

    }

}

9. En nu is het tijd om de applicatie uit te voeren. Hieronder staan de screenshots na het draaien van de applicatie.

Registreer de werknemer:

Na het aanmaken van de werknemer:

Onderstaande is uit de Cosmos database:

Update nu de data.

Uit de Cosmos DB:

Nadat de Delete-knop is aangeklikt:

Record verwijderd uit de Cosmos database:

Dit is het einde van de blog over Azure Cosmos DB. Tot in de volgende blog!