2015-10-21 3 views
1

Мы работаем над приложением MVC. В этом приложении у нас есть платежный модуль. После того, как пользователь начнет повторную подписку, приложение получит два ответа от PayPal для завершения платежа, с тем же TransactionId. Один через «Успешный URL», а другой - через прослушиватель IPN. Мы используем таблицу «Транзакция», чтобы сохранить детали транзакции в PayPal. Приложение проверяет наличие «Транзакции» в базе данных, получая ответ от Paypal. Таким образом, чистый результат - это первый ответ от PayPal, который будет вставляться в таблицу «Транзакция».Проблема с внедрением параллелизма Entity Framework

Недавно у нас возникли проблемы, связанные с параллелизмом работы с инфраструктурой Entity Frame. Если появится два ответа parellay, обе эти записи вставляют в таблицу транзакций с одним и тем же «идентификатором trnsction», даже если у нас есть код для проверки существования транзакции. Как предотвратить эту дублируемую вставку? Обе вставки происходят из разных CONTEXT.

 var ipnDetail = unitOfWork.TransactionDetailRepository.GetTransaction(transactionNumber); 
      if (ipnDetail == null) 
      { 
} 

Мы используем тот же код для обоих вставок. Единственное отличие состоит в том, что мы вызываем из разных контекстов EF.

enter image description here

Также можно отметить первую вставленную запись, имеющую больше времени, чем второй вставленной записи. Фактически мы устанавливаем дату из кода. Как решить эту проблему параллелизма?

Мы попытались использовать «ObjectContext.Refresh» для решения. Но это нам не помогает.

((IObjectContextAdapter)context).ObjectContext.Refresh(System.Data.Objects.RefreshMode.StoreWins, ((IObjectContextAdapter)context).ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added)); 

Любая помощь будет заметна. Обратите внимание, что приложение находится в рабочей среде.

С наилучшими пожеланиями,

Ranish

+0

Не могли бы вы поместить уникальный индекс в столбец транзакций в своем бэкэнде? Это предотвратит это. – ojf

+0

Спасибо. если я устанавливаю «уникальный индекс» в стороне sql, я думаю, что это предотвращает дублирование транзакций. Но проблема заключается в том, что мы должны знать ipnDetails == null или нет, исходя из того, что мы можем выполнять другую операцию. – Ranish

+0

- это ваш автоконкурс id?потому что это объяснит это ... первый вызов будет успешным, второй попытается вставить идентификатор и сбой с параллелизмом. – DevilSuichiro

ответ

0

Wrap вся проверка и вставки логики внутри TransactionScope.

using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew)) 
{ 
    // read & write logic here  

    scope.Complete();   
} 

RequiresNew приведет к новой транзакции, которые будут использоваться, и он должен быть заблокирован на уровне БД, чтобы ваш другой запрос должен ждать, пока первая не завершит сделку либо путем добавления Id или нет.

+0

Обратите внимание, что пользователь может произвести оплату parellaly. Также мы имеем первичное поле id в db. Мы считаем, что проблема связана с операцией Context upadation/Refresh – Ranish

1

Если у вас есть SQL Server 2014 или выше, команда слияния - именно то, что вам нужно. Это позволяет вам установить условие if в нужное место в операции.

Приведенный ниже пример вставляет новую транзакцию, если она не существует в базе данных. Большинство альтернатив включают запрос, за которым следует вставка, оставляя окно, в котором другое соединение может прокрасться в вставку до завершения вашей работы.

Вы можете найти ресурсы в Интернете о вызове хранимой процедуры из фреймворка сущности.

CREATE proc [dbo].[usp_InsertNewTransactionId](@transactionDate datetime2, @transactionId varchar(255)) 
as 
begin 
    ;with data as (select @transactionDate as transactionDate, @transactionId as transactionId) 
    merge transactions t 
    using data s 
     on s.transactionId = t.transactionId 
    when not matched by target 
    then insert ([date],transactionId) values (s.transactionDate, s.transactionId); 

end