我有下一个问题 我有用户。用户在数据库中有列 - 票证。 - 机票是内部货币。 现在,当用户点击网站购买 - 我去webapi ===> BL(班级图书馆)
我从数据库中取出用户 - 检查他是否有票,如果是 - 我做我的逻辑(我去DAL - 然后把这个计数器放下来)。
问题是 - 如果我点击网站上的按钮购买 - 这么快 - 我可以买两次。
示例
用户有1张票
他想买点东西 - 价格1票
用户在按钮BUY上快速点击2次
1个请求 转到WebApi ==>转到BL ==>从DAL用户从数据库获取并检查他是否有票证 - 是的他是===>做逻辑并将Ticket计数器置于0
2请求 转到WebApi ==>转到BL ==>从数据库中获取DAL用户并检查他是否有票证 - 是的他这里是问题 ===>做逻辑并将Ticket计数器置于0
所以我不知道如何防止这个错误....或者如何更好地重新制作数据库结构呢?
答案 0 :(得分:3)
您需要更改更新逻辑,使得几个并发更新只有一个会成功。
例如,如果您的数据库表包含TicketId
和TicketCount
字段,您会看到剩余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来清除该字段。
无论如何,逻辑与上面相同,但在数据库级别。