Skip to main content

Updating the service

info

Before continuing, ensure your workstation has been set up with the Core Components, as well as components specific to the language ecosystem you're working in: [JavaScript] [Java] [.Net] [Python] [Rust]

As part of this excercise, lets change the entity within the Order service to have different properties in the entity.

Currently, the order service entity has name db column and model property, alongwith inherited entity properties (id, modified, created)

Lets change it to have some additional properties customerID & status.

Updating the code

Copy paste below code in the order-service/OrderService.Persistence/Entities/OrderEntity.cs

namespace OrderService.Persistence.Entities;

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

[Table("order")]
public class OrderEntity : AbstractEntity<Guid>
{
[Column("name")]
[Required]
public string? Name { get; set; }

[Column("customer_id")]
public string? CustomerID { get; set; }

[Column("status")]
public string? Status { get; set; }

}

Running the schema migration using the .NET Entity Framework

From the root order-service folder run:

dotnet ef migrations add AddStatusCustomerId  --project OrderService.Persistence -s OrderService.Server

Above would add 2 migration files in the OrderService.Persistence/Migrations/ directory: _{datetime}__AddStatusCustomerId.cs & _{datetime}__AddStatusCustomerId.Designer.cs

Please take a look to see how the columns are getting added.

Add the new properties to the API

Update the core business logic

Update order-service/OrderService.Core/OrderServiceCore.cs with the code in the collapsed section

using Grpc.Core;
using OrderService.API;

using OrderService.Persistence.Entities;
using OrderService.Persistence.Models;
using OrderService.Persistence.Repositories;

namespace OrderService.Core;

public class OrderServiceCore : IOrderService
{
private readonly OrderRepository _orderRepository;

public OrderServiceCore(
OrderRepository orderRepository)
{

_orderRepository = orderRepository;
}
public async Task<CreateOrderResponse> CreateOrder(OrderDto request)
{
var order = new OrderEntity
{
Name = request.Name,
CustomerID = request.CustomerID,
Status = request.Status
};

_orderRepository.Save(order);
await _orderRepository.SaveChangesAsync();

return new CreateOrderResponse
{
Order = new OrderDto
{
Id = order.Id.ToString(),
Name = order.Name,
CustomerID = order.CustomerID,
Status = order.Status
}
};
}

public async Task<GetOrdersResponse> GetOrders(GetOrdersRequest request)
{
var startPage = Math.Max(1, request.StartPage);
var pageSize = Math.Max(Math.Min(request.PageSize, 100), 1);
PageRequest pageRequest = new PageRequest
{
PageSize = pageSize,
StartPage = startPage
};

var page = await _orderRepository.FindAsync(pageRequest);

var response = new GetOrdersResponse
{
TotalElements = page.TotalElements,
TotalPages = (int)page.TotalElements / pageSize
};
response.Orders.AddRange(page.Items.Select(order => new OrderDto
{
Id = order.Id.ToString(),
Name = order.Name,
CustomerID = order.CustomerID,
Status = order.Status
}));

return response;
}

public async Task<GetOrderResponse> GetOrder(GetOrderRequest request)
{
var order = await _orderRepository.FindByIdAsync(Guid.Parse(request.Id));
if (order == null)
{
throw new RpcException(new Status(StatusCode.NotFound, "Order not found"));
}

return new GetOrderResponse
{
Order = new OrderDto
{
Id = order.Id.ToString(),
Name = order.Name,
CustomerID = order.CustomerID,
Status = order.Status
}
};
}

public async Task<UpdateOrderResponse> UpdateOrder(OrderDto order)
{
var entity = await _orderRepository.FindByIdAsync(Guid.Parse(order.Id));
if (entity == null)
{
throw new RpcException(new Status(StatusCode.NotFound, "Order not found"));
}

entity.Name = order.Name;
entity.CustomerID = order.CustomerID;
entity.Status = order.Status;

_orderRepository.Update(entity);
await _orderRepository.SaveChangesAsync();

return new UpdateOrderResponse
{
Order = new OrderDto
{
Id = entity.Id.ToString(),
Name = entity.Name,
CustomerID = entity.CustomerID,
Status = entity.Status
}
};
}

public async Task<DeleteOrderResponse> DeleteOrder(DeleteOrderRequest request)
{
var order = await _orderRepository.FindByIdAsync(Guid.Parse(request.Id));
if (order == null)
{
throw new RpcException(new Status(StatusCode.NotFound, "Order not found"));
}

_orderRepository.Delete(order);

return new DeleteOrderResponse{Deleted = true};
}

}

Update the protobuf API specification

Replace the OrderDTO with code in the collapsed section
message OrderDto {
google.protobuf.StringValue id = 1;
string name = 2;
string customerID = 3;
string status = 4;
}

Create a new order to test the service changes

grpcurl -plaintext -d '{"name": "test", "customerID":"1121-1223-abcd-edfg", "status":"active"}' localhost:5030 \
a1p.apps.order_service.grpc.OrderService/CreateOrder
grpcurl -plaintext -d '{"start_page": "1", "page_size": "5"}' localhost:5030 \
a1p.apps.order_service.grpc.OrderService/GetOrders