学说:追踪缓慢变化的维度的历史

时间:2016-07-22 11:50:57

标签: database-design doctrine-orm symfony

我正在Symfony3 / Doctrine开发一种网上商店。为了简化操作,我们假设我有一个表Repairs和一个Parts。零件有名称和价格,维修可以使用许多零件,以及各种零件可用于各种维修(多对多)。维修的价格是零件价格和其他一些因素的总和。

慢慢改变维度

现在应该可以更改一个Part的价格,这应该会改变未来Repairs的价格。但是,数据库中已存在的任何Repairs都不应更改,因为它们用于会计,发票等。

"软更新"

使用SoftDeleteable可以轻松解决Part的问题。这样可以保持PartsRepairs之间的关系不变。更新实体会发生类似的事情。只有当重要的事情(例如价格)发生变化时,才应在数据库中更新实体。但是,似乎没有现成的代码。

我尝试了以下内容:

  • 只需删除旧实体并在每次更新时存储副本,这是代码密集型的,效率低下并且在数据库中留下大量垃圾。
  • Versionable,但这不适用于多对多实体
  • Loggable,但这会将更改写入单独的日志表中,而不是在表格中使用
  • EntityAudit,但这也不能做我想做的事情,不能用于多人对待。

以不同方式解决问题?

asked寻求我的技术解决方案before的帮助,但由于我认为这个问题很常见,我开始认为缺乏直截了当现成的解决方案意味着我以错误的方式解决问题。也许我应该简单地保存一个静态表进行计算,并在其中存储静态值(但这不允许在保持价格的同时更改某个修复的名称)?或?

1 个答案:

答案 0 :(得分:1)

免责声明:您的问题非常广泛,因此可能有一个足够好的解决方案。下面这个只是我的意见。

我认为您应该重新考虑您的域名。再想想"价格"实际上是。正如您已经注意到它根据观点而变化。在您的示例中,有两种情况:

  • 当前( base )产品价格。
  • 当时的价格是Rapair。 (实际上支付金额)

但是在同样的价格上还有更多的观点。价格可能不仅会随着时间的推移而改变,但它可能同时具有多个值 。我们假设您要实施折扣功能,如果Parts费用Repair费用> 100美元,则可享受5%的折扣。在这种情况下,两个客户可能在同一时间具有不同的价格。

考虑到上述情况,您可能会注意到,Part的价格随着时间的推移并不重要,但有两种不同的价格属性。一个基本价格,第二个付费价格。

由于付费价格可能具有从未作为基础存在的值(例如在折扣案例中),因此很明显,您正在处理有两个不同的值,只有通过事件可以具有相同的名称price。但它们属于两个不同的实体。

<强> TL;博士

您正在处理两个不同的值,它们应分开保存。

解决方案提案

而不是ManyToMany关系,您可以创建一个明确的实体RepairPart,它与Repair关系中的PartManyToOne实体相关,但它还将包含您将来可能需要的其他数据,但它们可能会在源Part表中更改。在这种情况下,这是它的价格。