如果Web Api控制器被快速连续击中会发生什么?

本文关键字:什么 连续 Api Web 控制器 如果 | 更新日期: 2023-09-27 18:02:25

我有一个Web Api 2(使用c#)控制器方法运行异步保存(RESTful POST方法)。我们的QA测试人员破坏了保存按钮(客户端问题已修复,与Q无关)。没有重复检查,这自然是将重复条目保存到db。

我实现了一个重复检查(duplicateCount只是选择与传递给post的项目完全相同的项目的数量,应该是0,并且它工作,细节无关):

        var duplicateCount = (fooCollection.CountAsync(aggregateFilter)).Result;
        if (duplicateCount > 0) { return BadRequest(); }

This check works…除了第一次按下按钮之外——保存了两个重复的条目,每个条目都来自于单个的控制器点击。

因此,在我看来,第二次控制器命中发生在第一次控制器命中设法将项目保存到db之前,因此重复检查通过。这可能吗?

我对理论比对具体的答案更感兴趣。此外,我知道我可以检查数据库中的副本,这更多的是一个概念问题。MongoDb部分真的只是为了完整性,我想它会是类似的,如果我正在做一个异步保存到SQL。

有人在评论里问我是怎么打电话的。它是通过RestAngular实现的,但在我看来这是无关紧要的,因为我知道控制器被点击的次数和我点击按钮的次数一样多。我也知道一个事实,它不会产生重复的单一命中。

如果Web Api控制器被快速连续击中会发生什么?

快速的回答是"是" -由于控制器可以同时在任意数量的线程上实例化,因此它就像多线程一样。您的代码不是"线程安全的",因为它的业务操作需要对共享信息的某些元素(在本例中是数据库的状态)放置排他锁。

您可以(我不建议)打开互斥锁或数据库事务来强制执行单线程行为,但是您的吞吐量会下降。

我个人不经常面对这个问题,因为我(可能不好)坚持我所有的实体都有Guid主键,并使用SQL Merge命令插入或更新。这可能是一个有用的模式(无论您向控制器发送多少次相同的"消息"-它永远不会保存副本)。