首页 > 解决方案 > 替代监视器来检查记录是否存在,如果不存在则写入

问题描述

因此,我有一些 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);
   }
}

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

标签: c#sql-serverasp.net-coreconcurrencyentity-framework-core

解决方案


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


推荐阅读