2015-09-26 2 views
0

У меня есть приложение + веб-сайт, в котором используется API, где вы можете приобрести товары для виртуальной валюты.Как запретить вызовы API более одного раза

Когда вы купили товар, вы можете вернуть деньги и вернуть свои деньги.

Ниже приведен какой-то псевдокод, чтобы его объяснить.

апи/заказ/возврат/{OrderID}

if(order.status == accepted) 
{ 
    order.status = refunded; 
    user.AddMoney(order.Amount); 
    dbcontext.saveChanges(); 
} 

проблема, если API вызывается как апи/заказ/возврат/21 несколько раз довольно быстро, он будет работать до того SaveChanges(); является успешным и будет AddMoney(); для пользователя более одного раза для одного и того же заказа.

Кто-нибудь знает решение для этого?

Благодаря

+1

Это может помочь. http://stackoverflow.com/questions/13404061/how-can-i-lock-a-table-on-read-using-entity-framework Вам необходимо заблокировать таблицу в течение всей транзакции. – CollinD

+0

Спасибо CollinD, это привело меня к поиску того, что мне нужно! – que

ответ

0

Я закончил тем, что делал так:

var vctx = new VenueContext(); 
     using(var dbtransaction = vctx.Database.BeginTransaction(IsolationLevel.RepeatableRead)) 
     { 
      try 
      { 
       var order = vctx.Orders.Include("Venue").Include("Transactions.MenuItem").FirstOrDefault(x => x.Id == orderid); 
       if (order.StatusId != 1) 
       { 
        return false; 
       } 
       if (status == 3 || status == 4) 
       { 
        vctx = MoneyRepository.AddMoney(order.UserId, order.Total * -1, vctx); 
       } 
       order.StatusId = status; 
       vctx.SaveChanges(); 
       dbtransaction.Commit(); 
      } 
      catch (Exception) 
      { 
       dbtransaction.Rollback(); 
       return false; 
      } 
     } 
     return true; 
    } 
0

Используйте замок, как в образце ниже

private Object thisLock = new Object(); 
if(order.status == accepted) 
{ 
lock(thisLock) 
{ 

if(order.status == accepted) 
{ 
    order.status = refunded; 
    user.AddMoney(order.Amount); 
    dbcontext.saveChanges(); 

} 
}  
} 
+0

Я использовал решение, которое я разместил выше. Ваше решение более простое, но я думаю, что это помешает другим пользователям возвращать свои продукты одновременно с блокировкой оператора только одним потоком? – que

+0

блокировка должна завернуть проверку 'order.status == accepted', иначе она не имеет никакого значения. После прохождения проверки рано или поздно внутренний код будет выполнен более одного раза. Когда вы завершаете проверку, после того, как будет сделано первое возмещение, следующая проверка будет неудачной (order.status! = Принято), чтобы запустить выполнение. – Hopeless

+0

@Hopeless, спасибо, сделал редактирование, чтобы разместить это. - В очередь, я не понимаю, как несколько пользователей могут иметь один и тот же продукт? Мое понимание было бы в том, что каждый продукт будет уникально назначен пользователю, который его купил. пожалуйста, исправьте мое понимание – shat90

Смежные вопросы