实体框架中的多个/快速ajax请求和并发问题

时间:2012-08-13 20:28:08

标签: entity-framework asp.net-mvc-4

我有一个asp.net MVC4应用程序,我使用Unity作为我的IoC。我的控制器的构造函数接收一个存储库,该存储库接收一个UnitOfWork(DBContext)。一切似乎工作正常,直到来自同一会话的多个ajax请求发生得太快。由于并发问题,我收到Store update, insert, or delete statement affected an unexpected number of rows (0)错误。这是从ajax请求调用的方法:

public void CaptureData(string apiKey, Guid sessionKey, FormElement formElement)
{
        var trackingData = _trackingService.FindById(sessionKey);
        if(trackingData != null)
        {
             formItem = trackingData.FormElements
                          .Where(f => f.Name == formElement.Name)
                          .FirstOrDefault();

             if(formItem != null)
             {
                formItem.Value = formElement.Value;
                _formElementRepository.Update(formItem);
             }
        }
}

这只发生在ajax请求快速发生时,意味着快速。当请求以正常速度发生时,一切似乎都很好。这就像应用程序需要时间来赶上。不知道我需要如何处理我的存储库中的并发检查,所以我不会错过更新。此外,我尝试将“MultipleActiveResultSets”设置为true,但没有帮助。

1 个答案:

答案 0 :(得分:1)

正如您在评论中提到的,您正在使用行版本列。本专栏的目的是防止同一行的并发覆盖。您有两个操作:

  • 读取记录 - 读取记录和当前行版本
  • 更新记录 - 使用指定的密钥和行版本更新记录。行版本会自动更新

现在,如果这些操作是由并发请求执行的,您可能会收到:

  • 请求A:阅读记录
  • 请求B:阅读记录
  • 请求A:写记录 - 更改行版本!
  • 请求B:写入记录 - 触发异常,因为在读取记录期间检索到的行版本的记录不存在

异常被告知您正在尝试更新过时数据,因为已经有更新记录的新版本。通常,您需要刷新数据(通过从数据库重新加载当前记录)并尝试再次保存它们。在高度并发的情况下,此处理可能会重复多次,因为只是您的数据库旨在防止这种情况。您的选择是:

  • 删除行版本,让请求根据需要覆盖该值。如果您确实需要并发请求处理,并且您很乐意拥有“一些”价值,那么这可能就是您的选择。
  • 不允许并发请求。如果您需要处理所有更新,您最可能还需要他们的实际订单。在这种情况下,您的应用程序不应允许并发请求。
  • 请改用SQL /存储过程。通过使用表提示,您将能够在读取操作期间锁定记录,并且在第一个保存更改和提交或回滚事务之前,其他任何请求都无法读取该记录。