When dealing with one Aggregate Root (AR) at a time, things are simple since the Repository should wrap anything realted to that AR in a transaction (or commit). The problem is when dealing with multiple ARs and/ore when the persistence doesn't support transactions.
For that case, the solution is a bit tricky as it involves beign comfortable with the concept of eventual consistency (aka things will be consistent... eventually), message driven architecture, saga and idempotency.
In a nutshell, one Ar is updated which generates one or more events. The other AR subscribe to those events and update their state as well generating other events. The infrastructure, the message bus in this case, will ensure that each event is published at least once. Things can go wrong but the message bus will eventually deliver the messages (but not quite in the same milisecond).
The event handler idempotency ensures that an operation can be repeated without changing the initial result, while the saga manages the flow of events and possbile commands (as a result of an event).
So, all the business objects involved will be in sync eventually, but it will take a bit of time to achieve that (from 1 milisecond to minutes and hours).
It's not easy and straightforward, however it's not THAT hard and it's very usable both in local and disitrbuted scenarios.
For a distributed app you can use NServiceBus