在实体框架中对订单到产品关系建模

时间:2014-01-03 09:21:14

标签: .net entity-framework

这不是一个技术问题,而是一个关于如何建模数据的问题。

首先,我正在使用Entity Framework构建数据存储。

我一直在为小型企业创建一个电子商务网站,我已经创建了一个似乎可行的系统,但我现在意识到我犯了一个根本性的错误(我想!)。

我有一个订单对象和一个产品对象。该产品显然包含有关产品的所有详细信息,包括价格。

我现在已经创建了100多种产品,这些产品现在位于名为Products

的表中

因此,当我创建订单时,会在订单中添加单个产品或多个产品。所以订单现在包含对products表的引用。

这很好用,直到我意识到我可能想要改变订单中产品的价格(提供折扣等)。由于订单中的产品与产品表相关联,如果我对价格进行更改,则会更改所有先前和将来订单的价格。

所以看起来我需要2个产品表。一个是当前的待售产品清单,一个是订购对象的子产品。

对此进行建模的最佳方法是什么?我确定我需要2个不同的产品表。

对此的任何指导将不胜感激。

9 个答案:

答案 0 :(得分:7)

为什么不创建一个捕获实际支付价格的订单商品实体?这样做是相当标准的。

答案 1 :(得分:6)

您可以通过多种方式实现这一目标,而您希望实现的复杂性将决定哪种解决方案最适合您。

就我个人而言,我不会直接(如果有的话)将产品链接到产品。我的订单将包含订单行,其中包含描述,单价,数量等。如果您想启用导航或链接回产品,那么我会在订单行上添加产品链接。产品的价格永远不会计入订单成本,它只是在订购时复制到订单行,同时也适用任何折扣/修改。您可以安全地修改订单行,而不会影响任何产品或其他订单。订单行只会涉及单个订单。

我假设产品和订单之间的链接是多对多的?如果是这样在链接表上(这可能意味着您必须首先在实体框架代码中手动指定交叉表),您可以添加价格转换属性。这可能只是一个百分比 - 100%没有变化90%的10%折扣等

您可以完全将产品与产品分开,然后您可以根据您想要的复杂程度为特定用户,用户组甚至订购数量的产品分配给定价格。这可能会证明很多工作,但听起来并不像你需要的那样。

此外,虽然我可能不想这样做,但您可以使每个产品条目都不可变(它永远不会改变),并且可以通过创建新记录然后标记原始产品或新创建的产品来模拟更改为“隐藏”(缺乏一个更好的术语),一般不可访问。在提供产品折扣的情况下,您将修改与订单相关联的产品,并在幕后修改它真正要做的是创建一个新的“隐藏”产品,并在其上加上新价格。您必须在视图产品页面上处理此问题,以检测产品的状态并相应地处理它。如果使用订单历史记录页面并允许导航到您已经给予大量一次折扣的产品,则需要确保您的应用程序不允许以该价格订购其他订单。

答案 2 :(得分:2)

您可以拥有以下表格/实体:

Product (ProductId, ProductName, ProductDescription, Price, ...)
Order (OrderId, DateTime, ...)
OrderItem (OrderItemId, OrderId, ProductId, Price, Quantity, ...)

如果需要,您还可以拥有Stock表。

答案 3 :(得分:2)

对于你的解决方案,我会做以下模型

 public class Product
{
    public int Id { get; set; }
    public double Price { get; set; }

    public bool Archived { get; set; }
}

public class OrderProduct
{
    public int Id { get; set; }
    public Order Order { get; set; }
    public Product Product { get; set; }
    public double Price { get; set; }
    public int Total { get; set; }
}


public class Order
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public List<OrderProduct> Products { get; set; }
    public Discount Discount { get; set; }
    public DateTime CreatedAt { get; set; }
}

public class Discount
{
    public int Id { get; set; }
    public DiscountType Type { get; set; }
    public string Code { get; set; }
    public double Amount { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public List<Product> ProductsToApply { get; set; }
    public List<Product> RequiredProducts { get; set; }
}

public enum DiscountType
{
    Amount,
    Percent
}

产品 - 我认为无需解释

折扣 - 如果您需要降价,那么您应该在产品上更改它。但是,由于您可以为特定产品创建限时优惠,但您可以添加所需产品以获得折扣,因此您可以享受折扣优惠。 但是为了解决您的主要问题,我会在两个表中进行,订单 OrderProduct ,我会保存客户购买的商品数量和价格。

订单 - 如果客户购买了产品,那么您可以参考产品及其当前价格创建订单并向其添加OrderProducts。也可以订购,如果有的话附加折扣

答案 4 :(得分:1)

没有必要,只有冗余才能拥有两个产品表。您需要的是订单表中的额外字段,用于指定每种产品的销售单价。在一天结束时,当您想要计算资金流量时,您应该参考订单表中设置的单价。

为了进一步开发,您可能需要产品价格的历史记录表。因此,您可以回顾历史来分析价格调整。

答案 5 :(得分:1)

上个月,当我在ecomm网站上工作时,情况类似。我使用了类似的方法(如Rob West和Allan所建议的),其中每个Order都有多个OrderItems。每个OrderItem都有一个Product的链接,但除此之外,它还有2个额外的字段,ItemCost,Discount,SubTotal。

在创建订单时,我会将Product的价格复制到OrderItem中,然后将应用折扣。

另外,我在Order表上有一个GroupDiscount列,这将允许我对整个订单提供集体折扣。

这在生产中一直没有任何问题。

答案 6 :(得分:0)

通常你所做的是有一个名为OrderProduct的表或任何你想要调用它的表,然后该表将有一些必须在订单到位后及时冻结的表。 您的实体最终将如下所示:

public class Product
{
    public int Id {get; set;}
    public string ProductName {get; set;}
    public virtual ICollection<OrderProduct> OrderProducts {get; set;}
}

public class Order
{
    public int Id {get; set;}
    public virtual ICollection<OrderProduct> OrderProducts {get; set;}
}

public class OrderProduct
{
    public int Id {get; set;}
    public virtual Order Order {get; set;}

    public virtual Product Product {get; set;}//this is optional, 
    //you would only include it if you need to query 
    //other information about the product 
    //that wouldn't change (color, size, type, etc.)
}

答案 7 :(得分:0)

您可以使用其他方法。尝试在单独的表中存储价格(和更改历史记录)。

简而言之,创建表ProductPrice(ProductId,Price,StartDate)并将其用于所有价格变化。 OrderItem应该引用ProductPrice而不是Product。对于每个新订单获取最后价格(通过StartDate)。

对于自定义OrderItem oprions(vip客户端的折扣,交付的额外成本等),在OrderItem表中创建字段。如果有许多不同因素影响价格,请创建单独的表格。例如,PriceModification(修改规则列表)和PriceModificationInOrderItem。

有关更多信息,请参阅如何在关系理论中创建历史表。例如这篇文章: http://database-programmer.blogspot.ru/2008/07/history-tables.html

答案 8 :(得分:-1)

只需将PricePaid字段添加到OrderItem表即可。价格可能会发生变化,但订单仍然存在。