Azure Cosmos DB bắt đầu với tên gọi Dự án Florence Florence năm 2010 để giải quyết các điểm đau của nhà phát triển phải đối mặt với các ứng dụng quy mô lớn trong Microsoft. Quan sát rằng những thách thức trong việc xây dựng các ứng dụng phân tán trên toàn cầu không phải là vấn đề duy nhất đối với Microsoft, năm 2015 microsoft đã tạo ra thế hệ đầu tiên của công nghệ này cho các nhà phát triển Azure dưới dạng Azure DocumentDB. Kể từ đó, Microsoft đã thêm dần các tính năng mới và giới thiệu các khả năng mới quan trọng. Năm 2017, Microsoft đã đổi tên Azure DocumentDB thành Azure Cosmos DB và mở rộng hỗ trợ cho nhiều giao diện cơ sở dữ liệu khác nhau
Comos db có nhiều ưu điểm như:
- Tốc độ và thông lượng cao với độ trễ thấp và phân phối dữ liệu toàn cầu.
- Khả năng mở rộng tự động và linh hoạt theo nhu cầu của ứng dụng.
- Hỗ trợ nhiều giao diện cơ sở dữ liệu như NoSQL, MongoDB, PostgreSQL, Apache Cassandra, Apache Gremlin và Table.
- An ninh và tính sẵn sàng cao với sao lưu liên tục và bảo mật doanh nghiệp.
Comos db hỗ trợ nhiều API cơ sở dữ liệu như
- SQL API: Interacts with a document database for JSON data.
- MongoDB API: Existing MongoDB applications can leverage this API to interact with Cosmos DB.
- Table API: Supports Azure table storage operations.
- Gremlin API: Used to interact with graph data.
- Cassandra API: Existing Apache Cassandra applications (for example, apps dependent on column stores) can use this API to work with Cosmos DB.
Cài đặt
- Azure Subscription
- Azure Cosmos DB Emulator
Azure Subscription
Azure Cosmos DB Emulator
- QuickStart: Bạn sẽ lấy chuỗi connection string hoặc URI - Primary Key ở đây
- Exporer: Quản lý Database, Container
Database và container
Dữ liệu trong container được chia thành các phân vùng logic dựa trên partiton key mà bạn chọn khi tạo container.
Partiton key là một thuộc tính của dữ liệu giúp cosmos DB phân phối dữ liệu hiệu quả giữa các phân vùng. Partiton key quyết định vị trí của các tài liệu.
- Partiton key nên có nhiều giá trị khác nhau để phân bổ dữ liệu đồng đều giữa các phân vùng logic và vật lý.
- Partiton key nên phù hợp với các truy vấn thường xuyên của bạn để tránh truy vấn qua nhiều phân vùng.
- Partiton key nên có khả năng mở rộng ngang khi dữ liệu tăng lên.
- Partiton key nên được chọn trước khi tạo bảng vì không thể thay đổi sau đó.
/// <summary>
/// Create the database if it does not exist
/// </summary>
private async Task CreateDatabaseAsync()
{
// Create a new database
this.database = await this.cosmosClient.CreateDatabaseIfNotExistsAsync(databaseId);
Console.WriteLine("Created Database: {0}\n", this.database.Id);
}
// </CreateDatabaseAsync>
// <CreateContainerAsync>
/// <summary>
/// Create the container if it does not exist.
/// Specifiy "/LastName" as the partition key since we're storing family information, to ensure good distribution of requests and storage.
/// </summary>
/// <returns></returns>
private async Task CreateContainerAsync()
{
// Create a new container
this.container = await this.database.CreateContainerIfNotExistsAsync(containerId, "/LastName", 400);
Console.WriteLine("Created Container: {0}\n", this.container.Id);
}
Primary key
Ví dụ: nếu bạn có một container lưu trữ thông tin người dùng, bạn có thể chọn Department làm partition key và Id làm item id. Khi đó, primary key của mỗi item sẽ là Department + Id
Ví dụ
Trong ví dụ này, mình làm chức năng thêm sửa xóa sử dụng WebPI
Cài đặt package: Microsoft.Azure.Cosmos
Tạo Employee Model
public class EmployeeModel
{
public string? id
{
get;
set;
}
public string? Name
{
get;
set;
}
public string? Country
{
get;
set;
}
public string? City
{
get;
set;
}
public string? Department
{
get;
set;
}
public string? Designation
{
get;
set;
}
public DateTime? JoiningDate
{
get;
set;
}
}
Delete Database
/// <summary>
/// Delete the database and dispose of the Cosmos Client instance
/// </summary>
private async Task DeleteDatabaseAndCleanupAsync()
{
DatabaseResponse databaseResourceResponse = await this.database.DeleteAsync();
// Also valid: await this.cosmosClient.Databases["FamilyDatabase"].DeleteAsync();
Console.WriteLine("Deleted Database: {0}\n", this.databaseId);
//Dispose of CosmosClient
this.cosmosClient.Dispose();
}
// </DeleteDatabaseAndCleanupAsync>
Tạo connect với container:
Container containerClient = cosmosDbClient.GetContainer(CosmosDbName, CosmosDbContainerName);
return containerClient;
Thêm 1 item vào container
var container = ContainerClient();
var response = await container.CreateItemAsync(employee, new PartitionKey(employee.Department));
return Ok(response);
Lấy 1 item lên
var container = ContainerClient();
var response = await container.ReadItemAsync<EmployeeModel>(employeeId, new PartitionKey(partitionKey));
Update item:
var container = ContainerClient();
var res = await container.ReadItemAsync<EmployeeModel>(emp.id, new PartitionKey(partitionKey));
//Get Existing Item
var existingItem = res.Resource;
//Replace existing item values with new values
existingItem.Name = emp.Name;
existingItem.Country = emp.Country;
existingItem.City = emp.City;
existingItem.Department = emp.Department;
existingItem.Designation = emp.Designation;
var updateRes = await container.ReplaceItemAsync(existingItem, emp.id, new PartitionKey(partitionKey));
Cuối cùng là xóa 1 item
var container = ContainerClient();
var response = await container.DeleteItemAsync<EmployeeModel>(empId, new PartitionKey(partitionKey));
Tổng hợp lại, chúng ta sẽ có đoạn code như sau:
[Route("api/[controller]/[action]")]
[ApiController]
public class EmployeeController : ControllerBase
{
// Cosmos DB details, In real use cases, these details should be configured in secure configuraion file.
private readonly string CosmosDBAccountUri = "https://localhost:8081";
private readonly string CosmosDBAccountPrimaryKey = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
private readonly string CosmosDbName = "EmployeeManagementDB";
private readonly string CosmosDbContainerName = "Employees";
/// <summary>
/// Commom Container Client, you can also pass the configuration paramter dynamically.
/// </summary>
/// <returns> Container Client </returns>
private Container ContainerClient()
{
var cosmosDbClient = new CosmosClient(CosmosDBAccountUri, CosmosDBAccountPrimaryKey);
Container containerClient = cosmosDbClient.GetContainer(CosmosDbName, CosmosDbContainerName);
return containerClient;
}
[HttpPost]
public async Task<IActionResult> AddEmployee(EmployeeModel employee)
{
try
{
var container = ContainerClient();
var response = await container.CreateItemAsync(employee, new PartitionKey(employee.Department));
return Ok(response);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpGet]
public async Task<IActionResult> GetEmployeeDetails()
{
try
{
var container = ContainerClient();
var sqlQuery = "SELECT * FROM c";
var queryDefinition = new QueryDefinition(sqlQuery);
var queryResultSetIterator = container.GetItemQueryIterator<EmployeeModel>(queryDefinition);
var employees = new List<EmployeeModel>();
while (queryResultSetIterator.HasMoreResults)
{
FeedResponse<EmployeeModel> currentResultSet = await queryResultSetIterator.ReadNextAsync();
foreach (EmployeeModel employee in currentResultSet)
{
employees.Add(employee);
}
}
return Ok(employees);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpGet]
public async Task<IActionResult> GetEmployeeDetailsById(string employeeId, string partitionKey)
{
try
{
var container = ContainerClient();
ItemResponse<EmployeeModel> response = await container.ReadItemAsync<EmployeeModel>(employeeId, new PartitionKey(partitionKey));
return Ok(response.Resource);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpPut]
public async Task<IActionResult> UpdateEmployee(EmployeeModel emp, string partitionKey)
{
try
{
var container = ContainerClient();
var res = await container.ReadItemAsync<EmployeeModel>(emp.id, new PartitionKey(partitionKey));
//Get Existing Item
var existingItem = res.Resource;
//Replace existing item values with new values
existingItem.Name = emp.Name;
existingItem.Country = emp.Country;
existingItem.City = emp.City;
existingItem.Department = emp.Department;
existingItem.Designation = emp.Designation;
var updateRes = await container.ReplaceItemAsync(existingItem, emp.id, new PartitionKey(partitionKey));
return Ok(updateRes.Resource);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpDelete]
public async Task<IActionResult> DeleteEmployee(string empId, string partitionKey)
{
try
{
var container = ContainerClient();
var response = await container.DeleteItemAsync<EmployeeModel>(empId, new PartitionKey(partitionKey));
return Ok(response.StatusCode);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
}
Tham khảo
Tìm hiểu về Azure Cosmos DB trong Microsoft Azure.
CRUD Operations In Azure Cosmos DB SQL API Using ASP.NET Core Web API C#
Nhận xét
Đăng nhận xét