Doctrine: tracking history of slowly changing dimensions

南笙酒味 提交于 2019-12-23 03:36:29

问题


I'm developing a type of web shop in Symfony3/Doctrine. In order to simplify things, let's say I have a table Repairs and one Parts. Parts have a name and a price, and a Repair can use many Parts, as well as various Parts can be used in various Repairs (Many-to-many). The price of a Repair is the sum of the prices of the Parts and some other factors.

Slowly changing dimensions

Now it should be possible to change the price of one Part, and this should change the price of future Repairs. However, any Repairs that already exist in the Database should not change, as they are used for accounting, invoicing and such.

"Soft-updateable"

Deleting a Part is easily solved with SoftDeleteable. This keeps the relationships between Parts and Repairs intact. Something similar should happen for updating Entities. Only if something vital (such as the price) changes, the Entity should be updated in the database. However, there seems to be no ready-made code.

I've tried the following:

  • Simply deleting the old Entity and storing a copy upon every update, which is code-intensive, inefficient and leaves lots of junk in the database.
  • Versionable, but this does not work on many-to-many entities
  • Loggable, but this writes the changes in a separate log table, not in the table I'm using
  • EntityAudit, but this also doesn't do what I want and can't be used on many-to-manies.

Approach the problem differently?

I've asked for help with my technical solutions before, but Since I believe that the problem is a common one, I'm starting to think that the lack of straightforward, ready-made solutions mean that I'm approaching the problem in the wrong way. Perhaps I should simply keep a static table for accounting with static values stored in them (but this would not allow changing the name of a certain Repair while keeping the price)? Or?


回答1:


Disclaimer: Your question it pretty broad, therefore there may be more then one good enough solution. This one below is just my opinion.

I think you should reconsider your domain. Think again about what the "price" actually is. As you've already noticed that it's varying depending on point of view. In your examples there were two cases:

  • current (base) price of product.
  • the price in the past at the time, the Rapair was made. (actually paid amount)

But there are even more points of view on the same price. The price may not only change over time, but it may have multiple values at the same time. Let's say, you want to implement discounts feature, where if Parts for a Repair cost >100$ in total, you give a 5% discount. In this case two clients may have different price at the same exact time.

Taking above into account, you could notice, that it's not actually matter of Part's price over time, but there are two different price properties. One base price, and the second paid price.

Since paid price may have values that never existed as a base (e.g. in discount case), it's clear, that you're dealing with two different values that only by accidence can have the same name price. But they belong to two different entities.

tl;dr

You're dealing with two different values and they should be kept separately.

Solution proposal

Instead of ManyToMany relation, you could make an explicit entity RepairPart, which would relate to both Repair and Part entities in ManyToOne relation, but it will also contain additional data that you may need in the future, but they may change in source Part table. In this case it's the price.



来源:https://stackoverflow.com/questions/38525756/doctrine-tracking-history-of-slowly-changing-dimensions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!