public override Task SaveAsync(TAggregateRoot aggregateRoot) { if (aggregateRoot == null) { throw new ArgumentNullException(nameof(aggregateRoot)); } var uncommittedEvents = DispatchEvents(aggregateRoot).ToArray(); if (uncommittedEvents.Any()) { using (var stream = _eventStore.OpenStream(typeof(TAggregateRoot).FullName, aggregateRoot.Identity, (int)uncommittedEvents.First().Version)) { var commitId = OperationContext.CommandId ?? Guid.NewGuid(); foreach (var @event in uncommittedEvents) { var headers = new Dictionary <string, object> { { KnownHeaders.EventClrType, @event.GetType().AssemblyQualifiedName }, { KnownHeaders.AggregateRootClrType, typeof(TAggregateRoot).AssemblyQualifiedName } }; if (OperationContext.CorrelationId.HasValue) { headers.Add(KnownHeaders.CorrelationId, OperationContext.CorrelationId); } if (OperationContext.UserId.HasValue) { @event.CreatedBy = OperationContext.UserId.Value; headers.Add(KnownHeaders.UserId, OperationContext.UserId); } stream.Add(new EventMessage { Body = @event, Headers = headers.Union(OperationContext.CustomParameters()).ToDictionary(k => k.Key, v => v.Value) });; } try { stream.CommitChanges(commitId); } catch (DuplicateCommitException dce) { stream.ClearChanges(); _logger.LogWarning($"Duplicate commit {commitId} detected, skipping...", dce); } catch (global::NEventStore.ConcurrencyException cex) { stream.ClearChanges(); throw new ConcurrencyException(cex.Message, cex); } catch { stream.ClearChanges(); throw; } finally { aggregateRoot.ClearEvents(); } } } return(Task.CompletedTask); }