如果数据库中的条目数不只是为了可读性而改变,为什么要为购物车创建一个新的“CartItem”实体?

问题描述 投票:0回答:1

无需详细说明,现在我有两个实体:发票和产品。如果表中的记录总数没有减少,而是添加了一个新表(如果这个判断错误,正确我)

发票代码:

    public class Invoice
    {
        [Key]
        public long Id { get; set; }

        ///Any property

        public virtual ICollection<Product> CurrentProducts { get; set; } = new HashSet<Product>();
        
        ///Any property
 
    }

产品代码: 任何东西都可以是产品

    public class Product
    {
        [Key]
        public int Id { get; set; }

        ///Any property

        public virtual ICollection<Invoice> Invoices { get; set; } = new HashSet<Invoice>();

        ///Any property
    }

商品代码:

    public class CatItem
    {
        [Key]
        public int Id { get; set; }

        ///Any property

        public short Quantity { get; set; }

        public virtual int ProductId { get; set; }     
        public virtual Product Product { get; set; }

        public virtual long InvoiceId { get; set; }     
        public virtual Invoice Invoice { get; set; }

        ///Any property
    }

带/不带 CartItem 示例的数据库: enter image description here

我明白通过 cartItem 做什么更正确,但是没有更好的实现购物车的做法吗?

c# asp.net-web-api shopping-cart
1个回答
0
投票

如果

Product
表应该仅用作发票上的项目列表,那么它可能就足够了,但您至少应该将
Product
表重命名为
InvoicePosition
.

如果您打算在其他地方使用

Product
表,比如列出您商店中的可用产品,那么您肯定想要规范化这些表。您的多对多示例中的
Product
表在这种(以及许多其他)场景中根本不起作用。 在您的多对多示例中,您有多个名称相同但价格不同的产品。对于每张发票,您都需要一个单独的位置。我无法想象它除了用作
InvoicePosition
桌子之外还有什么用途。

如果你想进一步规范你的表格,并使它们更灵活,你可能需要考虑创建一个单独的

Price
表,与 ProductId、当前价格和此类价格可用时的日期范围。看起来基于“苹果”产品,您希望支持给定产品的价格变化。

所以,更灵活一点的数据库方案可能看起来像这样:

public class Invoice {
   public long Id { get; set; }
   public long CartId { get;set; }
   public List<InvoicePosition> Positions { get; set; }
}

public class InvoicePosition {
  public long Id { get; set; }
  public long InvoiceId { get; set; }
  public int CartItemId { get; set; }
  public decimal Value { get; set; }
  public int Quantity { get; set; }
}

public class Product {
  public int Id { get; set; }
  public string Name { get; set; }
  public AvailableQuantity { get; set; } // should be probably also moved to some kind of a warehouse model
  public List<Price> Prices { get; set; }
}

public class Price {
  public long Id { get; set; }
  public int ProductId { get; set; }
  public decimal Value { get; set; }
  public DateTimeOffset From { get; set; }
  public DateTimeOffset To { get; set; }
}

public class Cart {
   public long Id { get; set; }
   public List<CartItem> Items { get;set; }
}

public class CartItem {
   public long Id { get; set; }
   public long CartId { get; set; }
   public int ProductId { get; set; }
   public long PriceId { get; set; }
   public int Quantity { get; set; }
}

我希望,其中大部分都相当容易理解。你可能会有疑问,在

CartItem
内部引用
InvoicePosition
而不是简单地引用一个
Product
有什么好处? 这并非完全必要,但是,它可以帮助您应用并更轻松地跟踪额外的价格调整因素,例如折扣或特别促销。 并且拥有已订购和已开具发票的历史记录(它们肯定可能不同,例如下订单后仓库中缺少物品)绝对非常有用。

© www.soinside.com 2019 - 2024. All rights reserved.