Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 防止多请求-WebAPI_C#_Sql Server_Asp.net Web Api - Fatal编程技术网

C# 防止多请求-WebAPI

C# 防止多请求-WebAPI,c#,sql-server,asp.net-web-api,C#,Sql Server,Asp.net Web Api,我还有一个问题 我有一个用户。用户在数据库中有列-票证。-票是国内货币。 现在当用户点击网站购买-我去webapi==>BL(类库) 我把用户从DB中带出来——检查他是否有票,如果有——我做我的逻辑(然后我去DAL——把这个计数器放下) 问题是——若我点击网站上的button BUY——那个么快——我可以买两次 示例 用户有1张票证 他想买点东西——一张票的价格 用户快速点击按钮购买2次 1个请求 转到WebApi==>转到BL==>BL从数据库中从DAL用户处获取并检查他是否有票证---是的,

我还有一个问题 我有一个用户。用户在数据库中有列-票证。-票是国内货币。 现在当用户点击网站购买-我去webapi==>BL(类库)

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

问题是——若我点击网站上的button BUY——那个么快——我可以买两次

示例

用户有1张票证

他想买点东西——一张票的价格

用户快速点击按钮购买2次

1个请求 转到WebApi==>转到BL==>BL从数据库中从DAL用户处获取并检查他是否有票证---是的,他有===>执行逻辑并将票证计数器设置为0

2请求 转到WebApi==>转到BL==>从数据库中从DAL用户处获取BL,并检查他是否有票证---是的,他有这是问题所在==>执行逻辑并将票证计数器设置为0


因此,我不知道如何防止此错误……或者如何更好地为此重新创建数据库结构?

创建一个临时变量,在处理过程中保存购买状态。 此变量可以包含一些要角色化的用户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来清除该字段


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

您需要更改更新逻辑,以便在多个并发更新中只有一个会成功

例如,如果您的DB表中有
TicketId
TicketCount
字段,您会看到剩余的
n
票证,您希望减少票证数量,而不是这样做

UPDATE Ticket
SET TicketCount=@NewTicketCount
WHERE TicketId=@TicketId
这样做:

UPDATE Ticket
SET TicketCount=@NewTicketCount
WHERE TicketId=@TicketId AND TicketCount=@OldTicketCount
当您从多个线程同时运行第二次更新时,只有一次更新成功,即更新一行。所有其他线程都会看到此请求更新零行。他们应该将其视为失败的指示,并将相应的状态代码返回给Web API的调用者

我正在使用EF6.0


然后你可以依靠它,它会自动为你做类似的事情。

你是在使用Direct ado.net还是在ORM中使用实体框架(或其他东西)?我询问的原因是SQLServer可以选择使用版本控制行,EF可以利用这一点为您提供并发检查。如果你使用ado.net,你仍然可以利用它,但你必须手动实现。我使用EF 6.0如果你不能处理多个按钮事件,你可以在第一次单击后禁用按钮。然后你可以实现:请参阅。您希望存储用户的版本值,并将其传递给对web api的任何调用。然后,您应该将更新后的值作为响应发送回,以便可以重用。如果您尝试多次更新相同的值,EF将为您执行检查并引发异常。由于OP使用实体框架,因此值得注意的是,它支持开箱即用的乐观并发,并且(通过某些配置)可以生成此类更新查询并在并发冲突时生成异常(更新了0行)。@Evk谢谢,我没有看到那条评论。