我们正在开发MVC应用程序。在此应用程序中,我们有一个支付模块。一旦用户开始定期订阅,应用程序将从paypal获得两个响应,以完成付款,具有相同的TransactionId。 一个是通过“成功网址”,另一个是通过IPN监听。 我们使用“交易”表来保存paypal交易详情。 应用程序将检查数据库中是否存在“TransactionId”,同时从Paypal获取响应。因此,净结果是来自paypal的第一个响应将插入“交易”表。
最近我们遇到了与Entity Frame工作并发相关的问题。如果两个响应parellay到来,两个记录都插入到具有相同“trnasction id”的事务表中,即使我们有检查transactionid存在的代码。 我们如何防止这种重复插入? 插入都是从不同的上下文发生的。
var ipnDetail = unitOfWork.TransactionDetailRepository.GetTransaction(transactionNumber);
if (ipnDetail == null)
{
}
我们使用相同的代码进行插入。唯一不同的是我们从不同的EF上下文中调用。
您还可以注意到第一个插入的条目具有比第二个插入记录更长的时间。实际上我们是从代码设置日期。 我们如何解决这个并发问题?
我们尝试使用“ObjectContext.Refresh”作为解决方案。但它对我们没有帮助。
((IObjectContextAdapter)context).ObjectContext.Refresh(System.Data.Objects.RefreshMode.StoreWins, ((IObjectContextAdapter)context).ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added));
任何帮助都会很明显。请注意,应用程序处于生产环境中。
最诚挚的问候,
Ranish
答案 0 :(得分:1)
如果您有SQL Server 2014或更高版本,那么merge命令正是您所需要的。它允许您将if条件放在操作中的正确位置。
如果数据库中不存在新的transactionId,则下面的示例将插入新的transactionId。大多数替代方案都涉及一个查询后跟一个插入,留下一个窗口,其中另一个连接可以在你的完成之前潜入插入。
您可以在互联网上找到有关从实体框架调用存储过程的资源。
average
答案 1 :(得分:0)
将整个检查和插入逻辑包装在TransactionScope中。
using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
// read & write logic here
scope.Complete();
}
RequiresNew将导致使用新事务,并且应该在数据库级别上阻止它,因此您的另一个请求应该等到第一个请求完成,或者通过添加Id来完成事务。