Класс TransactionScope
маскирует исключения.Скорее всего, происходит то, что что-то внутри этой области выходит из строя (вызывает исключение), а TransactionAbortedException
- это просто побочный эффект, возникающий при выходе из блока using
.
Попробуйте обернуть все внутриTransactionScope
в блоке try-catch
, с перебросом внутри catch
и установкой там точки останова;вы должны увидеть реальную ошибку.
Еще одна вещь, TransactionScope.Complete
должна быть последним оператором, выполненным до конца блока using
, содержащего TransactionScope
.В этом случае вы, вероятно, должны быть в порядке, так как на самом деле вы не выполняете какую-либо работу впоследствии, но помещаете вызов Complete
во внутреннюю область видимости, что приводит к более подверженному ошибкам коду.
Обновление:
Теперь, когда мы знаем, что такое внутреннее исключение (транзакция, провоцирующая сбой), становится более понятным, что происходит.
Проблема в том, что внутри TransactionScope
, вы фактически открываете другое соединение с базой данных с GetUser
.Провайдер членства не знает, как повторно использовать DataContext
, который у вас уже открыт;он должен открыть свое собственное соединение, и когда TransactionScope
видит это, он пытается перейти к распределенной транзакции.
Это происходит сбой, потому что вы, вероятно, отключили MSDTC на любом веб-сервере, сервере базы данных,или и то, и другое.
Невозможно избежать распределенной транзакции, если вы собираетесь открыть два отдельных соединения, поэтому существует несколько способов решения этой проблемы:
Переместите GetUser
звонки за пределы TransactionScope
.То есть сначала «прочитайте» пользователей из поставщика членства в список, а затем начните транзакцию, когда вам действительно нужно начать вносить изменения.
Удалите вызовы GetUser
в целом ичитать информацию о пользователях непосредственно из базы данных на том же DataContext
или, по крайней мере, на том же соединении.
Включить DTC на всех серверах, участвующих в транзакции (на производительность будет влиять, когдатранзакция продвигается).
Я думаю, что вариант № 1 будет лучшим в этом сценарии;Маловероятно, что данные, которые вам нужно прочитать от поставщика членства, будут меняться между временем, когда вы их читаете, и временем, когда вы начинаете транзакцию.