IMO - это сценарий распределенной транзакции.
В примере, который вы упомянули, OrderService
& ReservationService
использует тот же контекст данных - деталь реализации, скрытая в коде.
Я не думаю, что правильно передавать эти знания до CompositionService
, заключая вызовы сервиса в TransactionScope, так как теперь сервис композиции знает о контексте общих данных и поэтому должен использовать TransactionScope для запуска код правильно.
На мой взгляд, код службы композиции должен выглядеть так:
try{
if(orderService.TryCreateOrder(orderData)){
if(reservationService.TryMakeReservation(orderData)){
reservationService.Commit();
orderService.Commit();
}
else{
orderService.TryRollbackOrder(orderData);
throw new ReservationCouldNotBeMadeException();
}
}
else{
throw new OrderCouldNotBeCreatedException();
}
}
catch(CouldNotRollbackOrderServiceException){
// do something here...
}
catch(CouldNotCommitServiceException){
// do something here...
}
В этом случае метод OrderService.TryCreateOrder вставит ордер со статусом PendingReservation или каким-либо другим соответствующим статусом, который указывает, что ордер вставлен, но не завершен. Это состояние будет меняться при вызове коммитов в сервисах (шаблон UnitOfWork?)
В этом случае детали реализации сервисов полностью скрыты от потребителя сервиса, в то время как составление также возможно, независимо от базовой детализации реализации.
НТН.