As you alluded to, one way to manage things is to specify the version you're expecting to act on when you Load
the aggregate (there's an overload for that).
The commit phase will then [via the Domain] yield a ConcurrencyException
if your generated events clash with ones:-
- already present [that you didn't load into your aggregate].
- written concurrently by competing processes
Make sure you do >1 read of the .doc file that the NuGet package puts into your project - it covers the fundamentals of how the JO EventStore approaches the handling of this.
UPDATE for clarity NB While this all works and is sometimes necessary, in general you'll find [and as a default should be working hard to arrive in the happy place where] you can manage most of these conflict resolution things by making your Commands naturally idempotent in nature and/or using natural conflict resolution mechanisms in your system as a whole in order to not need to lean on your Event Store to provide such a low level guard (e.g. etags, retrying Commands in the event of a conflict etc.). If you find yourself going down this path to any major degree in practice, I'd recommend discussing your strategy with sufficient real-world use cases on the DDD-CQRS list.