Вы путаете два типа областей транзакций: Rebus имеет свою собственную область транзакций, которую вы можете использовать следующим образом:
using (var scope = new RebusTransactionScope())
{
await bus.Send(oneMessage);
await bus.Send(anotherMessage);
// no messages have been sent at this point
//
//
// but when we do this ? they will be sent
await scope.CompleteAsync();
}
Когда вы находитесь в обработчике Rebus, нет необходимости используйте RebusTransactionScope
, потому что обработчик будет иметь свою собственную область транзакции, которая завершается после того, как ваш код завершил выполнение без каких-либо исключений.
Другая область транзакции является частью. NET. Это то, что вы включаете, когда вызываете
Configure.With(...)
.(...)
.Options(o => o.HandleMessagesInsideTransactionScope())
.(...)
, что приведет к выполнению обработчиков Rebus внутри System.Transactions.TransactionScope
.
(...) Мне нужна вся обработка в Стремитесь быть атомом c (...)
К сожалению, это никогда не может быть атомом c*, потому что система очередей и ваша база данных не могут быть зачислены в одну транзакцию. Я имею в виду, что они могут ПРОДОЛЖИТЬ быть, подняв вашу транзакцию до РАСПРЕДЕЛЕННОЙ СДЕЛКИ, используя протокол двухфазной фиксации для организации фиксаций, но, к сожалению, распределенные транзакции медленны и сопровождаются кучей проблем.
Обычно Так как Rebus обеспечивает «хотя бы раз доставку» сообщений, вам лучше убедиться, что ваш код идемпотентен.
(*), по крайней мере, в общем, он не может