假设我有一个包含订单行的订单,并且我们有一个多用户系统,不同的用户可以在其中添加订单行。订单被持久化到数据库
一个业务规则是一个订单只能创建 10 个订单行。
我有什么选择来确保这条规则不被破坏?我应该检查内存并应用锁还是通过过程在数据库中处理这个?
假设我有一个包含订单行的订单,并且我们有一个多用户系统,不同的用户可以在其中添加订单行。订单被持久化到数据库
一个业务规则是一个订单只能创建 10 个订单行。
我有什么选择来确保这条规则不被破坏?我应该检查内存并应用锁还是通过过程在数据库中处理这个?
对于如何处理这个问题,您有很多选择,包括:触发器、约束、业务规则逻辑和数据结构。
我的偏好如下。将所有插入/删除/更新包装到存储过程中的订单行中,并且只允许应用层通过存储过程访问表。然后,此过程可以强制执行此业务规则和其他业务规则。它还会在运行时锁定表以进行更新,因此只有一个用户可以在任何给定时刻更改表。
类似的方法是在表上使用插入而不是触发器。当这个(和其他)业务规则失败时,这将导致插入失败。与此相关的主要问题是可维护性。一张桌子上的一个触发器很好。但是,如果您开始对具有级联插入/删除的多个表执行此操作,则最终可能会引发一场噩梦。
正如其中一条评论所建议的那样,您可以尝试使用约束来执行此操作。您肯定会想要测试它的性能,因为您几乎无法控制约束的实现方式。
此外,您可以在订单表中有十个订单行列。这将着重执行此规则。但是,为每个订单行设置单独的列并且必须处理诸如删除之类的问题是有成本的。
在这种情况下不适合的另一种选择是在应用程序级别强制执行业务规则。但是,对于多个并发用户,您应该在数据库中完成这项工作。
假设最坏的情况,大量(又名超过 2 个)用户都同时尝试向单个订单添加行。(更糟糕的是,假设他们都在尝试添加不同数量的行,尽管一次不超过 10 行——GUI 至少可以控制那么多)。这会导致以下情况:
为了避免这种情况,需要有某种形式的中央“检查点”或调节器,所有用户都可以在其中确定他们是否可以添加行。如果他们通过了检查点,他们可以添加;如果不通过,他们就不能。检查点必须是绝对的:一旦收到/分配批准,该决定会影响所有后续检查(即,当您检查并被授予第 10 行时,之前没有其他人被授予,并且随后也没有其他人被授予) .
有几种方法可以实现这一点,它们都涉及数据库事务(ACID 属性)。事务必须始终尽可能简短,以避免与其他用户发生阻塞或死锁。这可能是棘手的代码,对我来说,实现/控制该过程的最佳方法是通过存储过程(如@Gordon Linoff 所说)。