public async Task SaveEventsAsync <T>(string aggregateId, IEnumerable <IDomainEvent> events, int aggregateVersion, string streamName) where T : AggregateRoot { _logger.LogDebug("SaveEvents {type} {AggregateId} {AggregateVersion}", typeof(T), aggregateId, aggregateVersion); var t = typeof(T); //var con = await _provider.GetActiveConnection().ConfigureAwait(false); var con = _provider.GetActiveConnection(); var domainEvents = events as IDomainEvent[] ?? events.ToArray(); //der eventstore fängt bei 0 an, wir im leeren aggregate bei -1 , das erste event erzeugt die version 0, also auch bei 0 // die version, die das aggregate vor den neuen events hatte var originalVersion = aggregateVersion - domainEvents.Length; //das ist die nummer, bei der der stream jetzt stehen sollte, so wird sichergestellt, dass in der zwischnzeit keine events geschrieben wurden var expectedVersion = originalVersion; //var expectedVersion = originalVersion == 0 ? ExpectedVersion.NoStream : originalVersion; var eventHeaders = new Dictionary <string, string> { // {EventStoreConstants.AggregateNameTypeHeader, t.AssemblyQualifiedName}, // {EventStoreConstants.AggregateShortClrTypeHeader, t.GetTypeShortName()}, { EventStoreConstants.AggregateIdHeader, aggregateId } }; var aggNameAttr = t.GetCustomAttribute <AggregateNameAttribute>(); if (aggNameAttr != null) { eventHeaders.Add(EventStoreConstants.AggregateNameHeader, aggNameAttr.Aggregate); eventHeaders.Add(EventStoreConstants.BoundedContextNameHeader, aggNameAttr.BoundedContext); } var eventsToSave = domainEvents.Select(e => MessageExtensions.ToEventData(e, eventHeaders)).ToList(); if (eventsToSave.Count < WritePageSize) { try { var result = await con .AppendToStreamAsync(streamName, expectedVersion, eventsToSave, _provider.OpsCredentials) .ConfigureAwait(false); _logger.LogTrace("EventStore - WriteResult: {@WriteResult}", result); } catch (WrongExpectedVersionException weException) { throw new ConcurrencyException(weException.Message, weException) { ExpectedVersion = aggregateVersion, AggregateType = typeof(T) }; } } else { try { var transaction = await con .StartTransactionAsync(streamName, expectedVersion, _provider.OpsCredentials) .ConfigureAwait(false); var position = 0; while (position < eventsToSave.Count) { var pageEvents = eventsToSave.Skip(position).Take(WritePageSize); await transaction.WriteAsync(pageEvents).ConfigureAwait(false); position += WritePageSize; } await transaction.CommitAsync().ConfigureAwait(false); } catch (WrongExpectedVersionException weException) { throw new ConcurrencyException(weException.Message, weException) { ExpectedVersion = aggregateVersion, AggregateType = typeof(T) }; } } }