我在库存跟踪网络应用程序中工作。我在设计用户界面时遇到了一些问题,尤其是编辑购买清单。
以下是我的购买表
的概述数据结构+------+-------+------+------+-----------
| ID | Name | Price| QTY | Date |
+------+-------+------+------+-----------
|B03-13|Goods1 |10000 |10 |2014-3-10
|B03-14|Goods2 |10000 |20 |2014-3-10
|B03-13|Goods3 |20000 |5 |2014-4-10
平均价格表
+------+----------+----------
| ID | Avg Price| Date |
+------+----------+----------
|B03-13|1000 |2014-3-10
|B03-13|500 |2014-3-10
|B03-13|2000 |2014-4-10
计算移动平均价格 (价格*总计)/总库存
想象一下,我们有1000行数据,当我们编辑数据时说它是第三个数据,当然应用程序会再次计算整个数据。编辑一行将导致最终的平均价格变化。所以我必须计算它之后的整行(在用户编辑的行之后),检查"平均价格"表和更新相关数据,用户每次更改都会进行更改。
在这种情况下,我们应该中止编辑数据"功能,或只是允许用户编辑他们插入的最后数据?
感谢您的回答,我希望它对其他有相同问题的人有用
答案 0 :(得分:0)
您的问题有多个方面,而且非常幸运。我将专注于一些相当随意选择的细节,其他人可能会涉及其他方面。
这是通过将所有更改放入单个事务来完成的。这样,当您更改购买金额或添加新购买时,给定商品的平均价格将同时更改。对于外部观察者,他们可以看到旧数据或新数据,但不能看到一个表被更改的不一致数据,但另一个表还没有。当然,这必须考虑数据库的实现细节,以及其事务系统和存储后端提供的ACID guarantees类型。
一种方法是在用户界面会话暴露给定数据进行修改后,锁定相关数据库行,防止其他人更改它们。
另一种方法是将Generation列添加到用户更改的所有表中。获取用户界面数据时,也会获取世代号。提交更改事务时,查询都符合where Purchase.Generation = ...
等条件。这样,任何源于陈旧数据的更改都将失败。
另一种与Generation列互操作的方式是提交与一代不相关的相关交易,但作为不关心现有价值的变更交易。例如,如果您以特定价格收到了一定数量的小部件,则在购买表中,您要么添加到现有行,要么创建新行。在AvgPrice表中,您将根据Purchase表中的相关值原子地修改该值。因此,在此期间,另一个用户可能已经购买了相同的项目并不重要:数据库将保持一致,无论如何,您获得100多个项目的行为将导致这样:某个地方的计数器将会上升(无论是现有的还是新的)。这就像是银行账户上的存款交易一样。
当然,从商业角度来看,我们可能仍然希望这样的交易失败,因为原来的用户可能不再需要购买这100件商品。
这取决于上下文。有时,如同银行存款一样,您不做任何事情,只需重试相同的交易,因为交易有一个" delta"语义而不是"取代新的价值"语义。退出是类似的,但并不完全:它是一个" delta"事务,但它可能以两种方式失败:
正在执行并发事务并中止此事务。在这种情况下,你总是重试。
事务失败,因为不再满足业务约束。例如,与此同时,余额低于满足退出所需的最低金额。这是一个艰难的失败,重试不会解决它。
其他时候,可以向用户呈现用于生成交易的数据旁边的更新数据,并突出显示已更改的内容。这取决于数据的呈现方式。例如,在库存表中,您可以在视觉上指示已更改的字段"同时"。然后将提示用户重新输入这些字段的期望值或增量,以明确确认仍然需要相同的改变。这将迫使重新考虑小部件购买,因为其他人已经订购了相同的小部件,等等。