试图在数据库中写入数据时出现 Guid 问题

Guid problem while attempting to write data in database

我正在尝试编写一个包含实体 FoodOrder 的送餐应用。

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; }
}

创建新的 Order 时会出现问题,因为我正在从 ICollection<Food> Foods 中的 Food 传递 Guid Id。我正在使用 MediatR 处理用户操作,以及 CreateOrderCommand class 和 Order class 本身之间的映射。

捕获的异常声称问题是来自 ICollection<Food> 的 Guid 已经存在。我应该如何映射食物集合,或者我应该将我的 ID 的 Guid 更改为简单的 int 或 string?

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

这是邮递员尝试在 OrderRepository 中添加新订单时捕获的异常,Key 是作为参数传递的 Food 中的 Guid。

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

这是从前端应用接收的数据

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;
    }

这是数据的处理程序。

我假设您的 Food 实体代表可用食物的目录,每个都有自己的 Guid 唯一标识符。

现在,我想,您正在尝试在 Order 上下文中创建一个订单,'uses' 在您的 Food 上下文中标识的食品项目。

在这种情况下,如果同一食品在同一订单中出现两次,或出现在其他订单中,那么因为您使用食品资源的唯一标识符作为订单聚合中某项的唯一键你会得到像上面那样的 PK 约束错误。

我认为您需要两个独立的实体:

  • 食物
  • OrderItem(指的是食物)

OrderItem 应该有自己的唯一键,有一列包含食物的 ID。

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; }
}