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

What Happens if a Web Api Controller is hit in rapid succession?

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

我实施了重复检查(duplicateCount 只是选择与传递给 post 的项目完全相同的项目数,应该是 0,它有效,细节无关):

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

此检查有效...除了第一个按钮混搭 - 保存了两个重复的条目,每个都来自一个单独的控制器点击。

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

与具体答案相比,我对理论更感兴趣。另外,我知道我也可以检查数据库中的重复项,这更像是一个概念性问题。 MongoDb 部分实际上只是为了完整性,我想如果我正在对 SQL 进行异步保存,它会是相似的。

编辑:有人在评论中问我是如何打电话的。它是通过 RestAngular 实现的,但在我看来这无关紧要,因为我知道控制器被击中的次数与我按下按钮的次数一样多。我也知道一个事实,它不会在一次点击中创建重复项。

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

您可以(我不推荐)打开一个 Mutex 或数据库事务来强制单线程行为,但您的吞吐量会下降。

我个人并不经常遇到这种情况,因为我(可能是坏的)坚持我的所有实体都具有 Guid 主键并使用 SQL Merge 命令来插入或更新。这可能是一个有用的模式(无论您向控制器发送相同的 "message" 多少次都没有关系——它永远不会保存重复项)。