Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# RavenDB并发、锁定文档等?_C#_.net_Concurrency_Ravendb_Optimistic Concurrency - Fatal编程技术网

C# RavenDB并发、锁定文档等?

C# RavenDB并发、锁定文档等?,c#,.net,concurrency,ravendb,optimistic-concurrency,C#,.net,Concurrency,Ravendb,Optimistic Concurrency,我不能100%确定如何解决这个问题,所以我将首先尝试说明我的问题。请忽略这是一个糟糕的示例或糟糕的数据结构设计,因为这只是一个示例 假设我们有一个叫做Person的类。Person类具有您期望的标准属性(姓名、年龄等)。它也有一个简单的PersonId和一个CompanyId。此外,它还有一个名为Code的特殊属性 在业务案例中,每个公司ID的代码都必须是唯一的。因此,它本质上是CompanyId+代码的复合密钥结构 我需要这样做,当有并发应用程序创建这些个人实体时,他们需要能够遵守这个约束 我

我不能100%确定如何解决这个问题,所以我将首先尝试说明我的问题。请忽略这是一个糟糕的示例或糟糕的数据结构设计,因为这只是一个示例

假设我们有一个叫做Person的类。Person类具有您期望的标准属性(姓名、年龄等)。它也有一个简单的PersonId和一个CompanyId。此外,它还有一个名为Code的特殊属性

在业务案例中,每个公司ID的代码都必须是唯一的。因此,它本质上是CompanyId+代码的复合密钥结构

我需要这样做,当有并发应用程序创建这些个人实体时,他们需要能够遵守这个约束

我已经研究了各种方法来实现这一点:

1) 我知道有一个Raven UniqueConstraints插件支持其中一些场景,但在这种情况下,插件是我想要避免的

2) 起初,我想让我的Person文档的raven ID成为CompanyId+代码的复合键。但是,业务需要允许用户更改代码。因此,这意味着如果用户编辑代码,我们最终将创建一个新的Person记录,并将CompanyId+NewCode指定为新的复合密钥ID。然后,以前的记录仍将浮动。当然我可以删除它,但它感觉有点脏

3) 我坚持使用唯一的Person Id,当任何应用程序点击端点创建新的Person时,我会从raven执行读取,以查看是否有包含我想要创建的相同公司Id和代码的Person记录。所以它会是这样的:

  • 读人记录
  • 个人记录不存在
  • 继续创建新的人员记录
当然,在简单化的场景中,这是可以的

但是,如果我们遇到两个应用程序同时运行并同时命中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 persistence做过类似的事情。它看起来像这样:

public class CodeConstraint
{
   public string Id { get; set;} //you manually provide the id
   public string PersonId { get; set;}
}
然后创建一个
,然后创建一个
编码约束
,并将编码约束分配给
。您可以将其包装到一个
TransactionScope
中,这样您就不会有孤立文档,以防它无法写入

此外,因为这是它自己的文档,所以如果您有任何竞争条件,Raven将为您提供并发异常

如果用户想要更改代码。然后创建一个新的“CodeConstraint”并将其分配给此人,并保留或删除旧的

对于奖金,您可以使用修改或创建时的时间戳扩展
codecontract
文档,因为您提到,您的部分需求是允许用户自定义此代码