Я работаю над приложением, которое должно создавать продукты (например, страховые полисы) при получении уведомлений о мгновенных платежах 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 назначается таблице пакетов. Тогда блокировка будет снята после того, как policyID назначен таблице пакетов. Я надеюсь, что другой поток, вызывающий этот же код, остановится, когда прочитает строку пакета, чтобы убедиться, что у него сначала нет идентификатора policyID. Когда будет снята блокировка первой транзакции, я надеюсь, что вторая транзакция увидит, что существует policyID, и, следовательно, вернется без вставки каких-либо строк в таблицу политик.
Примечание. Из-за структуры базы данных CRUD каждая хранимая процедура включала либо чтение (выбор), создание (вставку) или обновление.
Правильно ли используется изоляция транзакции RepeatableRead?
Спасибо.