防止多个请求 - WebAPI

时间:2017-06-09 18:28:53

标签: c# sql-server asp.net-web-api

我有下一个问题 我有用户。用户在数据库中有列 - 票证。 - 机票是内部货币。 现在,当用户点击网站购买 - 我去webapi ===> BL(班级图书馆)

我从数据库中取出用户 - 检查他是否有票,如果是 - 我做我的逻辑(我去DAL - 然后把这个计数器放下来)。

问题是 - 如果我点击网站上的按钮购买 - 这么快 - 我可以买两次。

示例

用户有1张票

他想买点东西 - 价格1票

用户在按钮BUY上快速点击2次

1个请求 转到WebApi ==>转到BL ==>从DAL用户从数据库获取并检查他是否有票证 - 是的他是===>做逻辑并将Ticket计数器置于0

2请求 转到WebApi ==>转到BL ==>从数据库中获取DAL用户并检查他是否有票证 - 是的他这里是问题 ===>做逻辑并将Ticket计数器置于0

所以我不知道如何防止这个错误....或者如何更好地重新制作数据库结构呢?

2 个答案:

答案 0 :(得分:3)

您需要更改更新逻辑,使得几个并发更新只有一个会成功。

例如,如果您的数据库表包含TicketIdTicketCount字段,您会看到剩余n张票,并且您希望减少票证数量,而不是这样做

UPDATE Ticket
SET TicketCount=@NewTicketCount
WHERE TicketId=@TicketId

这样做:

UPDATE Ticket
SET TicketCount=@NewTicketCount
WHERE TicketId=@TicketId AND TicketCount=@OldTicketCount

当您从多个线程同时运行第二个更新时,只有一个会成功,更新单个行。所有其他线程都会看到此请求更新零行。他们应该将其作为失败的指示,并将相应的状态代码返回给Web API的调用者。

  

我正在使用EF 6.0

然后你可以依靠EF 6 implementation of optimistic concurrency,它会自动为你做类似的事情。

答案 1 :(得分:0)

创建临时变量以在处理时保持BUYING状态。 此变量可以包含一些要配置的用户ID。

类似的东西:

      ' At the click...

      If UserBuyingNow is nothing
         UserIsBuying = User_ID
         ...
         (proceed to your logic)
         ...
         (at the end, clear the status variable)
         UserIsBuying = null
      else
         (user is already buying)
         exit
      End If

您也可以使用StoredProcedure在SQL上设置临时字段,在购买时设置为TRUE,并在处理结束时调用另一个StoredProcedure来清除该字段。

无论如何,逻辑与上面相同,但在数据库级别。