gpt4 book ai didi

c# - IsolationLevel.RepeatableRead 以防止重复

转载 作者:搜寻专家 更新时间:2023-10-30 20:33:13 25 4
gpt4 key购买 nike

我正在开发一个应用程序,该应用程序应该在收到 PayPal 即时付款通知时创建产品(如运输保险单)。不幸的是,PayPal 有时会发送重复的通知。此外,还有另一个第三方在从 PayPal 获取更新时同时执行网络服务更新。

这是涉及的数据库表的基本图。

// table "package"
// columns packageID, policyID, other data...
//
// table "insurancepolicy"
// columns policyID, coverageAmount, other data...

这是我想做的事情的基本图表:

using (SqlConnection conn = new SqlConnection(...))
{
sqlTransaction sqlTrans = conn.BeginTransaction(IsolationLevel.RepeatableRead);

// Calls a stored procedure that checks if the foreign key in the transaction table has a value.
if (PackageDB.HasInsurancePolicy(packageID, conn))
{
sqlTrans.Commit();
return false;
}

// Insert row in foreign table.
int policyID = InsurancePolicyDB.Insert(coverageAmount, conn);
if (policyID <= 0)
{
sqlTrans.Rollback();
return false;
}

// Assign foreign key to parent table. If this fails, roll back everything.
bool assigned = PackageDB.AssignPolicyID(packageID, policyID, conn);
if (!assigned)
{
sqlTrans.Rollback();
return false;
}
}

如果有两个(或更多)线程(或进程或应用程序)同时执行此操作,我希望第一个线程在没有 policyID 时锁定“package”行,直到创建策略并且policyID 分配给包表。然后将 policyID 分配给包表后,将释放锁。我希望调用此相同代码的另一个线程在读取包行时会暂停,以确保它首先没有 policyID。当第一个事务的锁被释放时,我希望第二个事务会看到那里的 policyID 并因此返回而不向策略表中插入任何行。

注意:由于 CRUD 数据库设计,每个存储过程都涉及读取(选择)、创建(插入)或更新。

这是对 RepeatableRead 事务隔离的正确使用吗?

谢谢。

最佳答案

如果 insert into Policy 在尝试插入重复项时只命中一些唯一性表约束,那会更安全、更干净。提高隔离级别会降低并发性并导致其他严重问题,例如死锁。

另一种方法是始终插入策略行,如果包已经附加到策略,则将其回滚:

begin tran (read committed)

/* tentatively insert new Policy */
insert Policy

/* attach Package to Policy if it's still free */
update Package
set Package.policy_id = @policy_id
where Package.package_id = @package_id and Package.policy_id is null

if @@rowcount > 0
commit
else
rollback

这在冲突很少见的情况下效果最好,这似乎就是您的情况。

关于c# - IsolationLevel.RepeatableRead 以防止重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/124313/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com