RavenDB并发、锁定文档等
本文关键字:文档 锁定 并发 RavenDB | 更新日期: 2023-09-27 17:59:39
我不能100%确定如何解决这个问题,所以我将首先说明我的问题。请忽略这是一个糟糕的例子或数据结构的糟糕设计,因为这只是一个例子。
想象一下,我们有一个名为Person的类。Person类具有您期望的标准属性(Name、Age等)。它还有一个简单的PersonId和一个CompanyId。此外,它还有一个名为Code的特殊属性。
在业务案例中,代码需要针对每个CompanyId是唯一的。因此,它本质上是CompanyId+Code的复合密钥结构。
我需要这样做,当有并发应用程序创建这些Person实体时,它们需要能够遵守这个约束。
我已经研究了各种方法来解决这个问题:
1) 我知道有一个Raven UniqueConstraints插件可以支持其中的一些场景,但在这种情况下,我想避免使用插件
2) 起初,我认为将Person文档的raven ID作为CompanyId+Code的复合密钥。但是,业务需要允许用户更改代码。因此,这意味着如果用户编辑代码,我们最终将创建一个新的Person记录,该记录的CompanyId+NewCodeSpecified将作为新的复合键ID。然后,上一个记录仍将浮动。我当然可以删除,但感觉有点脏?
3) 我坚持使用唯一的个人Id,当任何应用程序到达端点创建新的个人时,我会从raven中读取,看看是否有包含我想要创建的相同公司Id和代码的个人记录。所以它会是这样的:
- 读取人员记录
- 人员记录不存在
- 继续创建新的人员记录
当然,在简单场景的中也没问题
但是,如果我们遇到了两个应用程序同时运行并同时访问API服务(这是负载平衡的)的罕见情况,该怎么办。
那么它会像:
App1 App2
----- ----
Read person record Read person record
Verify it does not exist yet Verify it does not exist yet
Proceed to save new person Proceed to save new person
因此,他们最终都会制作一个具有相同公司Id+代码的个人记录。
我知道UseOptimisticConcurrency选项,但我相信只有当他们都试图修改同一记录,并且ETAG检查启动SaveChanges时,它才会抛出ConcurrencyException。
因此,我有点困惑于如何应对这种情况。
在这里冒险,但。。。
您可以制作一个名为CodeConstraint
的新文档。我见过NServiceBus Saga持久性做类似的事情。它看起来像这样:
public class CodeConstraint
{
public string Id { get; set;} //you manually provide the id
public string PersonId { get; set;}
}
然后创建一个Person
,然后创建CodeContraint
,并将代码约束分配给Person
。您可以将其封装到TransactionScope
中,这样就不会有孤立文档,以防它无法写入。
此外,因为这是它自己的文档,如果您有任何竞争条件,Raven将为您提供并发异常。
如果用户想要更改代码。然后创建一个新的"CodeConstraint"并将其分配给Person,并保留或删除旧的。
对于奖金,您可以扩展CodeContraint
文档,并为其修改或创建时间戳,因为您提到了您的部分要求是允许用户自定义此代码。