PayPal即時支払い通知を受信したときに商品(配送保険証券など)を作成することになっているアプリケーションに取り組んでいます。残念ながら、PayPalは重複した通知を送信することがあります。さらに、PayPalから更新を取得するときにWebサービスの更新を同時に実行している別のサードパーティもあります。
これは、関連するデータベーステーブルの基本的な図です。
// 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;
}
}
これを同時に実行する2つ(またはそれ以上)のスレッド(またはプロセスまたはアプリケーション)がある場合、ポリシーが作成されてpolicyIDが割り当てられるまで、最初のスレッドがpolicyIDを持たないときに「パッケージ」行をロックする必要がありますパッケージテーブルに。次に、policyIDがパッケージテーブルに割り当てられた後、ロックが解除されます。この同じコードを呼び出している他のスレッドがパッケージ行を読み取るときに一時停止して、最初にpolicyIDがないことを確認することを願っています。最初のトランザクションのロックが解除されたときに、2番目のトランザクションがpolicyIDが存在することを確認し、ポリシーテーブルに行を挿入せずに戻ることを期待しています。
注:CRUDデータベースの設計により、各ストアドプロシージャには、読み取り(選択)、作成(挿入)、または更新のいずれかが含まれていました。
これはRepeatableReadトランザクション分離の正しい使用法ですか?
ありがとう。