替代监视器来检查记录是不是存在,如果不存在则写入

Posted

技术标签:

【中文标题】替代监视器来检查记录是不是存在,如果不存在则写入【英文标题】:Alternative to a monitor to checking for the existence of a record, and writing it if it doesn't exist替代监视器来检查记录是否存在,如果不存在则写入 【发布时间】:2021-09-07 10:39:03 【问题描述】:

所以我有一些如下所示的 C# 代码(出于问题的目的进行了简化,任何错误都是我进行这些更改的结果)。可以从多个线程或上下文以异步方式调用此代码。这样做的全部目的是确保如果记录已经存在,则使用它,如果不存在,则创建它。可能是也可能不是很好的设计,但这可以按预期工作。

var timeout = TimeSpan.FromMilliseconds(500);
bool lockTaken = false;

try

    Monitor.TryEnter(m_lock, timeout, ref lockTaken);  // m_lock declared statically above
    if (lockTaken)
    
        var myDBRecord = _DBContext.MyClass.SingleOrDefault(x => x.ForeignKeyId1 == ForeignKeyId1
                                                              && x.ForeignKeyId2 == ForeignKeyId2);
        
        if (myDBRecord == null)
        
           myDBRecord = new MyClass
               
                ForeignKeyId1 == ForeignKeyId1,
                ForeignKeyId2 == ForeignKeyId2
                // ...datapoints
           ;
           _DBContext.MyClass.Add(myDBRecord);
           _DBContext.SaveChanges();
       
   
   else
   
       throw new Exception("Can't get lock");
   

finally

   if (lockTaken)
   
       Monitor.Exit(m_lock);
   

如果有很多请求进来,就会出现问题,它可能会使监视器不堪重负,如果它必须等待太久就会超时。虽然锁定的超时时间当然可以更短,但解决此类问题的首选方法是什么(如果有的话)?任何试图查看是否需要输入监视器的代码都需要成为该原子操作的一部分。

【问题讨论】:

WRT “很多请求进来”我们在谈论什么数字? @DaleK 不幸的是,除了每秒说出多个请求外,我无法告诉您。我可以降低监视器的超时时间,但在某些时候,如果请求的进入速度比发出的速度快,一些请求会掉到地板上。也许这是不可避免的。 好吧,如果您不确定,这有点难以建议 - 为什么不记录它呢?每秒多个请求不算什么...但也许您的代码很慢?您需要对要满足的需求有所了解,才能提出最佳解决方案。您还需要了解处理请求需要多长时间。因为分配一条记录应该是微不足道的。 这个逻辑是否应该存在于数据库层中? 网站中的这种逻辑看起来很奇怪,因为锁定在部署期间或如果有网络农场/花园时不起作用。 【参考方案1】:

我建议您完全摆脱监视器,而是处理重复键异常。无论如何,您必须处理尝试输入重复值的情况,为什么不直接这样做呢?

【讨论】:

以上是关于替代监视器来检查记录是不是存在,如果不存在则写入的主要内容,如果未能解决你的问题,请参考以下文章

检查模板中是不是存在变量,如果不存在则不会在记录器中导致错误

如果文件不存在则创建文件,然后将日志写入其中

如何使用ID检查记录,如果记录存在则更新如果不添加新记录

mysql插入数据时,判断是不是存在,存在则替代,不存在则直接插入,需要能够批量处理。

jQuery检查Cookie是不是存在,如果不存在则创建它

从 Excel VBA-检查访问表是不是存在/如果不存在,则创建/复制