TransactionScope нюансы - PullRequest
       24

TransactionScope нюансы

3 голосов
/ 14 февраля 2011

Давайте представим, что у меня есть два потока, которые выполняют некоторый ориентированный на базу данных код в специфичных для потока TransactionScopes с уровнем изоляции ReadCommitted.Но есть некоторая таблица, данные которой должны быть общими (дубликаты не должны создаваться).

using (var transactionScope = new TransactionScope(IsolationLevel.ReadCommitted))
{
   ...//some code
   if (!_someRepository.IsValueExists(value))
      _someRepository.AddData(value);
   ...//some code
   transactionScope.Complete();
}

Проблема в том, что оба потока могут проверить, существуют ли данные примерно в одно и то же время, а если нет - создать дублированные данные (ограничения не помогут: я должен предотвратить исключительную ситуацию).Я думаю, что это тривиальная проблема, но как ее обычно решают?

Я вижу следующее схематическое решение:

using (var transactionScope = new TransactionScope(IsolationLevel.ReadCommitted))
{
   ...//some code
   transactionScope.IsolationLevel = IsolationLevel.ReadUncommitted; //change Isolation Level
   lock (_sharedDataLockObject)
   {
      if (!_someRepository.IsValueExists(value))
         _someRepository.AddData(value);
   }
   transactionScope.IsolationLevel = IsolationLevel.ReadCommitted; //reset IsolationLevel
   ...//some code
   transactionScope.Complete();
}

Первая проблема с этим решением состоит в том, что TransactionScope не поддерживает IsolationLevelмодификация.Но давайте представим, что я использую транзакцию ADO.NET здесь.Тем не менее я не уверен, работает ли он.

Ответы [ 2 ]

2 голосов
/ 15 февраля 2011

В этом случае я бы сделал двойную проверку.

Сначала проверьте, что он не существует, здесь не требуется транзакция.

Затем запустите сериализуемую транзакцию.

Убедитесь, что он все еще не существует

, если он не существует, добавьте

коммит и закройте транзакцию.

1 голос
/ 21 февраля 2011

Я обычно решаю ту же самую проблему с ограничением БД и заключая всю транзакцию в попытку-перехват с повтором в блоке перехвата. Конечно, если по какой-то причине невозможно перезапустить транзакцию, это недопустимое решение (например, транзакция запущена вне вашего контроля - я не уверен, что вы подразумеваете под «Я должен предотвратить исключительную ситуацию»). «).

В зависимости от того, сколько времени обычно занимают транзакции, вы можете немного подождать перед повторной попыткой или сделать пару повторных попыток, но до тех пор, пока параллельная транзакция успешно завершится, ваша повторная попытка будет успешной.

Сложный бит часто заключается в том, как определить, что исключение было вызвано конкретным нарушением ограничения. Обычно для этого требуется некоторое эмпирическое тестирование, чтобы определить точный тип исключения и некрасивое соответствие строк сообщения об исключении.

...