简体   繁体   English

实体框架并发插入问题

[英]Entity Framework Concurrency insertion issue

We are working on a MVC application. 我们正在开发MVC应用程序。 In this application we have a payment module. 在此应用程序中,我们有一个付款模块。 Once user starting a recurring subscription, application will get two responses from paypal for payment complete, with the same TransactionId. 用户开始定期订阅后,应用程序将从Paypal收到两个付款请求,以完成付款,并使用相同的TransactionId。 One is through “Success Url” and other one is through IPN listener. 一种是通过“成功网址”,另一种是通过IPN侦听器。 We are using a “Transaction”table to keep paypal transaction details. 我们正在使用“交易”表来保存贝宝交易明细。 Application will check whether the “TransactionId” exist in the database, while getting a response from Paypal. 应用程序将在从Paypal收到响应的同时检查数据库中是否存在“ TransactionId”。 So net result is first response from paypal will insert to “Transaction” table. 因此,最终结果是贝宝的第一个响应将插入“交易”表。

Recently We are having issues related with Entity Frame work concurrency. 最近,我们遇到了与实体框架工作并发性相关的问题。 If the two response parellay comes, both the two records are inserting to the transaction table with the same “trnasction id”, even if we have the code for check existence of transactionid . 如果两个响应都来了,即使我们有检查transactionid是否存在的代码,两条记录也会插入到具有相同“ trnasction id”的事务表中。 How do we prevent this duplicate insertion? 我们如何防止重复插入? Both insertion is happening from different CONTEXT. 两种插入都发生在不同的上下文中。

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

We are using same code for both insertion. 两种插入方式都使用相同的代码。 Only difference is we are calling from different EF Context. 唯一的不同是我们从不同的EF上下文调用。

在此处输入图片说明

You can also note the first inserted entry having greater time than second inserted record. 您还可以注意第一个插入的条目比第二个插入的记录具有更多的时间。 Actually we are setting the date from code. 实际上,我们是从代码中设置日期。 How do we solve this concurrency issue? 我们如何解决这个并发问题?

We tried to use a “ObjectContext.Refresh” for a solution. 我们尝试使用“ ObjectContext.Refresh”作为解决方案。 But it does not help us. 但这对我们没有帮助。

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

Any help would be appreciable. 任何帮助将是可观的。 Please note that application is in production environment. 请注意,该应用程序处于生产环境中。

Best Regards, 最好的祝福,

Ranish Ranish

If you have SQL Server 2014 or greater, the merge command is exactly what you need. 如果您具有SQL Server 2014或更高版本,则完全需要合并命令。 It allows you to put the if condition at the right place in the operation. 它允许您将if条件放在操作中的正确位置。

The example below inserts your new transactionId if it does not exist in the database. 如果新的transactionId在数据库中不存在,则下面的示例将插入新的transactionId。 Most alternatives involve a query followed by an insert, leaving a window in which another connection can sneak in an insert before yours completes. 大多数替代方案都涉及一个查询,后跟一个插入,然后留下一个窗口,另一个连接可以在您完成之前在其中插入另一个窗口。

You can find resources on the internet about calling a stored procedure from entity framework. 您可以在Internet上找到有关从实体框架调用存储过程的资源。

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

Wrap the entire checking and inserting logic inside TransactionScope. 将整个检查和插入逻辑包装在TransactionScope中。

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

    scope.Complete();        
}

RequiresNew will cause a new transaction to be used and it should be blocked on the db level so your another request should be waiting until the first has completed the transaction either by adding the Id or not. RequiresNew将导致使用新事务,并且应在数据库级别将其阻塞,因此您的另一个请求应一直等待,直到第一个通过添加或不添加ID完成事务为止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM