Sql server 实体框架向上插入异步竞争条件。有更好的解决办法吗?

Sql server 实体框架向上插入异步竞争条件。有更好的解决办法吗?,sql-server,asp.net-mvc,entity-framework,Sql Server,Asp.net Mvc,Entity Framework,针对我的MVC5 WebAPI控制器的帖子检查数据库中是否存在项,如果不存在,则添加该项。如果它确实存在,它会更新它。它不使用主键标识字段,而是使用名为Name的字段 情况是这样的。 我有两个JSON客户端试图添加(发布)记录。 应用程序需要一些时间来预热。 应用程序启动后,第一次Post命中及其第一次异步查询将检查是否存在。 在等待时,第二个帖子点击并检查是否存在,没有找到任何记录,然后插入它。 然后第一个帖子从等待中返回,没有找到任何记录并插入它 所以首先我在Name字段上放了一个唯一的索引

针对我的MVC5 WebAPI控制器的帖子检查数据库中是否存在项,如果不存在,则添加该项。如果它确实存在,它会更新它。它不使用主键标识字段,而是使用名为Name的字段

情况是这样的。 我有两个JSON客户端试图添加(发布)记录。 应用程序需要一些时间来预热。 应用程序启动后,第一次Post命中及其第一次异步查询将检查是否存在。 在等待时,第二个帖子点击并检查是否存在,没有找到任何记录,然后插入它。 然后第一个帖子从等待中返回,没有找到任何记录并插入它

所以首先我在Name字段上放了一个唯一的索引,这样在上面的条件下它就会出错。 然后我的第一篇文章会因为重复索引违规而出错,这很好。 然后我将EF调用更改为非异步,认为我不会放弃(通过等待)第二篇文章,而我的第一篇文章只会继续执行read-Then-insert。这似乎允许两篇文章在没有任何重复插入错误的情况下完成。注意:第二篇文章现在是更新而不是插入

我假设这并不能消除多线程环境中索引冲突错误的可能性。 也许C#lock可以工作,但不能扩展到多个服务器。 从其他SO线程中,我了解到EF Upserts(AddOrUpdate)不是线程安全的,例如,不是真正的SQL Upserts

可能很多毫无戒心的程序员都有这样的bug,他们和我一样,刚刚开始对所有东西使用async/await


是否有更可靠的解决方法(没有存储过程)?

有两种方法可以解决此问题

  • 停止对数据库的第二次调用
  • 检查是否存在,并在事务中插入。然后第二个调用将等待第一个调用完成,它将看到数据已经在数据库中

  • 让第二次更新发生
  • 如果它没有产生任何问题,让第二次更新发生


    如果此问题发生在1000次调用中的1次,那么最好是进行一次额外的数据库更新,而不是1000次数据库锁。

    我不知道这与异步有什么关系。同步代码也会出现同样的问题,因为WebApi本身就是一个多线程的场景。