public async Task <IReadOnlyCollection <ICommittedDomainEvent> > CommitEventsAsync( IIdentity id, IReadOnlyCollection <SerializedEvent> serializedEvents, CancellationToken cancellationToken) { if (!serializedEvents.Any()) { return(new ICommittedDomainEvent[] {}); } var eventDataModels = serializedEvents .Select((e, i) => new EventDataModel { AggregateId = id.Value, AggregateName = e.Metadata[MetadataKeys.AggregateName], BatchId = Guid.Parse(e.Metadata[MetadataKeys.BatchId]), Data = e.SerializedData, Metadata = e.SerializedMetadata, AggregateSequenceNumber = e.AggregateSequenceNumber, }) .ToList(); _log.Verbose( "Committing {0} events to MSSQL event store for entity with ID '{1}'", eventDataModels.Count, id); const string sql = @" INSERT INTO EventFlow (BatchId, AggregateId, AggregateName, Data, Metadata, AggregateSequenceNumber) OUTPUT CAST(INSERTED.GlobalSequenceNumber as bigint) SELECT BatchId, AggregateId, AggregateName, Data, Metadata, AggregateSequenceNumber FROM @rows ORDER BY AggregateSequenceNumber ASC"; IReadOnlyCollection <long> ids; try { ids = await _connection.InsertMultipleAsync <long, EventDataModel>( Label.Named("mssql-insert-events"), cancellationToken, sql, eventDataModels) .ConfigureAwait(false); } catch (SqlException exception) { if (exception.Number == 2601) { _log.Verbose( "MSSQL event insert detected an optimistic concurrency exception for entity with ID '{0}'", id); throw new OptimisticConcurrencyException(exception.Message, exception); } throw; } eventDataModels = eventDataModels .Zip( ids, (e, i) => { e.GlobalSequenceNumber = i; return(e); }) .ToList(); return(eventDataModels); }
protected override async Task <IReadOnlyCollection <ICommittedDomainEvent> > CommitEventsAsync <TAggregate>(string id, IReadOnlyCollection <SerializedEvent> serializedEvents, CancellationToken cancellationToken) { var batchId = Guid.NewGuid(); var aggregateType = typeof(TAggregate); var aggregateName = aggregateType.Name.Replace("Aggregate", string.Empty); var eventDataModels = serializedEvents .Select((e, i) => new EventDataModel { AggregateId = id, AggregateName = aggregateName, BatchId = batchId, Data = e.Data, Metadata = e.Meta, AggregateSequenceNumber = e.AggregateSequenceNumber, }) .ToList(); Log.Verbose( "Committing {0} events to MSSQL event store for aggregate {1} with ID '{2}'", eventDataModels.Count, aggregateType.Name, id); const string sql = @" INSERT INTO EventFlow (BatchId, AggregateId, AggregateName, Data, Metadata, AggregateSequenceNumber) OUTPUT CAST(INSERTED.GlobalSequenceNumber as bigint) SELECT BatchId, AggregateId, AggregateName, Data, Metadata, AggregateSequenceNumber FROM @rows"; IReadOnlyCollection <long> ids; try { ids = await _connection.InsertMultipleAsync <long, EventDataModel>( cancellationToken, sql, eventDataModels) .ConfigureAwait(false); } catch (SqlException exception) { if (exception.Number == 2601) { throw new OptimisticConcurrencyException(exception.Message, exception); } throw; } eventDataModels = eventDataModels .Zip( ids, (e, i) => { e.GlobalSequenceNumber = i; return(e); }) .ToList(); return(eventDataModels); }