我有一个运行异步保存的Web Api 2(使用C#)控制器方法(RESTful POST方法)。我们的QA测试人员对保存按钮进行了捣碎(客户端问题已修复,与Q无关)。如果没有重复检查,自然会将重复的条目保存到数据库中。
我实施了一个重复检查(duplicateCount只选择与传递给帖子的项目完全相同的项目数,应为0,并且它有效,详细信息无关紧要):
var duplicateCount = (fooCollection.CountAsync(aggregateFilter)).Result;
if (duplicateCount > 0) { return BadRequest(); }
此检查有效...除了第一个按钮mash - 保存两个重复条目,每个条目来自单个控制器命中。
所以,在我看来,第二个控制器命中发生在第一个控制器命中设置将项目保存到数据库之前,因此重复检查通过。这可能吗?
我对这个理论比对特定答案更感兴趣。此外,我知道我也可以检查数据库中的重复项,这更像是一个概念性问题。 MongoDb部分实际上只是为了完整性,我想如果我正在对SQL执行异步保存,那将是类似的。
编辑:有人问我是如何在评论中进行调用的。这是通过RestAngular,但是它是无关紧要的,因为我知道控制器在按下按钮时会被击中很多次。我也知道它不会在一次点击中创建重复项。
答案 0 :(得分:1)
快速回答是“是” - 由于控制器能够同时在任意数量的线程上实例化,它就像多线程一样。您的代码不是“线程安全的”,因为它的业务操作需要在共享信息的某些元素上放置一个独占锁(在这种情况下是数据库的状态)。
您可以(我不建议)打开互斥锁或数据库事务来强制执行单线程行为,但您的吞吐量会变为坦克。
我个人并不经常这样做,因为我(可能很糟糕)坚持我所有拥有Guid主键的实体并使用SQL Merge命令来插入或更新。这可能是一种有用的模式(向控制器发送相同“消息”的次数并不重要 - 它永远不会保存副本)。