public async Task SaveAsync(Type aggregateType, IAggregateIdentity aggregateId, ICollection <IEvent> events, CancellationToken cancellationToken = default(CancellationToken)) { if (events.Count == 0) { return; } var partition = GetPartition(aggregateType, aggregateId); lock (eventStore) { Tuple <ETag, List <EventEntity> > eTaggedEvents; if (eventStore.TryGetValue(partition, out eTaggedEvents)) { // Check my last ETag against the current ETag var dbETag = eTaggedEvents.Item1; ETag myETag; if (idToETag.TryGetValue(aggregateId, out myETag) && myETag != dbETag) { throw new Ddd.Domain.Exceptions.ConcurrencyException(aggregateType, aggregateId); } var eventsEntities = eTaggedEvents.Item2; var lastVer = eventsEntities.Count; eventsEntities.AddRange(events.Select(e => ToEventEntity(e, ++lastVer))); var eTag = ETag.NewGuid(); eventStore[partition] = new Tuple <ETag, List <EventEntity> >( eTag, eventsEntities); idToETag[aggregateId] = eTag; // Remeber current ETag } else { var eTag = ETag.NewGuid(); var lastVer = 0; var eventsEntities = events.Select(e => ToEventEntity(e, ++lastVer)).ToList(); eventStore.Add(partition, new Tuple <ETag, List <EventEntity> >( eTag, eventsEntities)); idToETag.Add(aggregateId, eTag); // Remeber current ETag } } await bus.PublishAsync(events); }