Home > front end >  Guid problem while attempting to write data in database
Guid problem while attempting to write data in database

Time:11-20

I'm trying to write a Food Delivery app which has entities Food and Order.

public class Order
{
    [Key]
    public Guid OrderId { get; set; }
    public string UserName { get; set; }
    public DateTime OrderTime { get; set; }
    public ICollection<Food> Foods { get; set; }
    public decimal OrderTotal { get; set; }
}

public class Food
{
    [Key]
    public Guid FoodId { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string PictureUrl { get; set; }
    public double Rating { get; set; }
    public string Comments { get; set; }
}

The problem occurs when a new Order is being created, because I'm passing the Guid Id from Food in ICollection<Food> Foods. I'm using MediatR for handling user actions, and mapping between CreateOrderCommand class and Order class itself.

The exception that is caught is claiming that the problem is that Guid from ICollection<Food> already exists. How should I map the collection of foods otherwise, or should I change Guid to simple int or string for my Ids?

"An item with the same key has already been added. Key: 36708fa9-71df-4141-95d6-a73a65cd5dce"

This is the exception caught in postman while trying to add new order in OrderRepository, with the Key being the Guid from Food which is passed as parameter.

    public class CreateOrderCommand : IRequest<Guid>
{
    public string UserName { get; set; }
    public ICollection<Food> Foods { get; set; }
}

This is the data that is being received from the front end app

public async Task<Guid> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
    {
        var order = _mapper.Map<Order>(request);
        order.OrderTime = DateTime.Now;
        var user = await _userRepository.GetByUserNameAsync(request.UserName);
        GeoCoordinate userLocation = new GeoCoordinate(user.Latitude, user.Longitude);

        List<Restaurant> restaurants = (List<Restaurant>)await _restaurantRepository.ListAllAsync();
        List<double> distances = new List<double>();

        double minValue = 0;
        int minValuePosition = -1;

        //pronadji udaljenosti
        for (int i = 0; i < restaurants.Count; i  )
        {
            TimeSpan ts = DateTime.Now - restaurants[i].LastOrdered;
            if(ts.TotalMinutes >= 15)
            {
                GeoCoordinate restaurantCoords = new GeoCoordinate(restaurants[i].Latitude, restaurants[i].Longitude);
                distances.Add(userLocation.GetDistanceTo(restaurantCoords));
                minValue = distances[i];
                minValuePosition = i;
            }
            else
            {
                distances[i] = -1;
            }
        }

        //pronadji najmanju udaljenost koja je na listi
        for (int i = 0; i < distances.Count; i  )
        {
            if (distances[i] < 0)
                continue;
            if (distances[i] < minValue)
            {
                minValue = distances[i];
                minValuePosition = i;
            }
        }

        
        if(minValuePosition == -1)
        {
            //nema slobodnih restorana
            throw new Exception();
        }

        order.UserName = user.UserName;
        order.Foods = request.Foods;

        foreach(Food f in request.Foods)
        {
            order.OrderTotal  = f.Price;
        }

        order = await _orderRepository.AddAsync(order);

        return order.OrderId;
    }

This is the handler for the data.

CodePudding user response:

I presume that your Food entity represents a catalog of what food is available, each with its own Guid unique identifier.

Now, I think, you're trying to create an order in the Order context that 'uses' foods items identified in your Food context.

In this situation, if the same food item appears twice in the same order, or appears in other orders, then because you are using the unique identifier of the food resource as the unique key for an item in your Order aggregate you will get PK constraints errors like the one above.

I think you need two separate entities:

  • Food
  • OrderItem (which refers to a food)

The OrderItem should have its own unique key, with a column that includes the id of the food.

public class Order
{
    [Key]
    public Guid OrderId { get; set; }
    public string UserName { get; set; }
    public DateTime OrderTime { get; set; }
    public ICollection<OrderItem> OrderItems { get; set; }
    public decimal OrderTotal { get; set; }
}

public class OrderItem
{
    [Key]
    public Guid OrderItemId { get; set; }
    public Guid FoodId { get; set; }
    public int Quantity { get; set; }
    public decimal TotalPrice { get; set; }
}

public class Food
{
    [Key]
    public Guid FoodId { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string PictureUrl { get; set; }
    public double Rating { get; set; }
    public string Comments { get; set; }
}
  • Related