public override async Task UpdateAsync( IReadOnlyCollection <ReadModelUpdate> readModelUpdates, IReadModelContext readModelContext, Func <IReadModelContext, IReadOnlyCollection <IDomainEvent>, ReadModelEnvelope <TReadModel>, CancellationToken, Task <ReadModelEnvelope <TReadModel> > > updateReadModel, CancellationToken cancellationToken) { foreach (var readModelUpdate in readModelUpdates) { IMssqlReadModel mssqlReadModel; var readModelNameLowerCased = typeof(TReadModel).Name.ToLowerInvariant(); var readModelEnvelope = await GetAsync(readModelUpdate.ReadModelId, cancellationToken).ConfigureAwait(false); var readModel = readModelEnvelope.ReadModel; var isNew = readModel == null; if (readModel == null) { readModel = await _readModelFactory.CreateAsync(readModelUpdate.ReadModelId, cancellationToken).ConfigureAwait(false); mssqlReadModel = readModel as IMssqlReadModel; if (mssqlReadModel != null) { mssqlReadModel.AggregateId = readModelUpdate.ReadModelId; mssqlReadModel.CreateTime = readModelUpdate.DomainEvents.First().Timestamp; } readModelEnvelope = ReadModelEnvelope <TReadModel> .With(readModelUpdate.ReadModelId, readModel); } readModelEnvelope = await updateReadModel( readModelContext, readModelUpdate.DomainEvents, readModelEnvelope, cancellationToken) .ConfigureAwait(false); mssqlReadModel = readModel as IMssqlReadModel; if (mssqlReadModel != null) { mssqlReadModel.UpdatedTime = DateTimeOffset.Now; mssqlReadModel.LastAggregateSequenceNumber = (int)readModelEnvelope.Version.GetValueOrDefault(); } else { SetVersion(readModel, (int?)readModelEnvelope.Version); } var sql = isNew ? _readModelSqlGenerator.CreateInsertSql <TReadModel>() : _readModelSqlGenerator.CreateUpdateSql <TReadModel>(); await _connection.ExecuteAsync( Label.Named("mssql-store-read-model", readModelNameLowerCased), cancellationToken, sql, readModel).ConfigureAwait(false); } }
public override async Task UpdateReadModelAsync(string aggregateId, IReadOnlyCollection <IDomainEvent> domainEvents, CancellationToken cancellationToken) { var readModels = await _connection.QueryAsync <TReadModel>( cancellationToken, SelectSql, new { AggregateId = aggregateId }) .ConfigureAwait(false); var readModel = readModels.SingleOrDefault(); var isNew = false; if (readModel == null) { isNew = true; readModel = new TReadModel { AggregateId = aggregateId, CreateTime = domainEvents.First().Timestamp, }; } ApplyEvents(readModel, domainEvents); var lastDomainEvent = domainEvents.Last(); readModel.UpdatedTime = lastDomainEvent.Timestamp; readModel.LastAggregateSequenceNumber = lastDomainEvent.AggregateSequenceNumber; readModel.LastGlobalSequenceNumber = lastDomainEvent.GlobalSequenceNumber; var sql = isNew ? InsertSql : UpdateSql; await _connection.ExecuteAsync(cancellationToken, sql, readModel).ConfigureAwait(false); }
public async Task SetAsync(SettingKey settingKey, SettingGroupKey settingGroupKey, string value, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(value)) { throw new ArgumentNullException(nameof(value)); } var affectedRows = await _msSqlConnection.ExecuteAsync( cancellationToken, SetSql, new { Key = settingKey.Value, Value = value, GroupKey = settingGroupKey.Value }) .ConfigureAwait(false); if (affectedRows != 1) { throw new Exception($"Updating key '{settingKey}' didn't update any rows"); } }
public async Task DeleteEventsAsync(IIdentity id, CancellationToken cancellationToken) { const string sql = @"DELETE FROM EventFlow WHERE AggregateId = @AggregateId"; var affectedRows = await _connection.ExecuteAsync( Label.Named("mssql-delete-aggregate"), cancellationToken, sql, new { AggregateId = id.Value }) .ConfigureAwait(false); _log.Verbose( "Deleted entity with ID '{0}' by deleting all of its {1} events", id, affectedRows); }
public override async Task DeleteAggregateAsync <TAggregate, TIdentity>( TIdentity id, CancellationToken cancellationToken) { const string sql = @"DELETE FROM EventFlow WHERE AggregateId = @AggregateId"; var affectedRows = await _connection.ExecuteAsync( Label.Named("mssql-delete-aggregate"), cancellationToken, sql, new { AggregateId = id.Value }) .ConfigureAwait(false); Log.Verbose( "Deleted aggregate '{0}' with ID '{1}' by deleting all of its {2} events", typeof(TAggregate).Name, id, affectedRows); }
private async Task UpdateReadModelAsync( IReadModelContextFactory readModelContextFactory, Func <IReadModelContext, IReadOnlyCollection <IDomainEvent>, ReadModelEnvelope <TReadModel>, CancellationToken, Task <ReadModelUpdateResult <TReadModel> > > updateReadModel, CancellationToken cancellationToken, ReadModelUpdate readModelUpdate) { IMssqlReadModel mssqlReadModel; var readModelId = readModelUpdate.ReadModelId; var readModelEnvelope = await GetAsync(readModelId, cancellationToken).ConfigureAwait(false); var readModel = readModelEnvelope.ReadModel; var isNew = readModel == null; if (readModel == null) { readModel = await _readModelFactory.CreateAsync(readModelId, cancellationToken) .ConfigureAwait(false); mssqlReadModel = readModel as IMssqlReadModel; if (mssqlReadModel != null) { mssqlReadModel.AggregateId = readModelId; mssqlReadModel.CreateTime = readModelUpdate.DomainEvents.First().Timestamp; } readModelEnvelope = ReadModelEnvelope <TReadModel> .With(readModelUpdate.ReadModelId, readModel); } var readModelContext = readModelContextFactory.Create(readModelId, isNew); var originalVersion = readModelEnvelope.Version; var readModelUpdateResult = await updateReadModel( readModelContext, readModelUpdate.DomainEvents, readModelEnvelope, cancellationToken) .ConfigureAwait(false); if (!readModelUpdateResult.IsModified) { return; } readModelEnvelope = readModelUpdateResult.Envelope; if (readModelContext.IsMarkedForDeletion) { await DeleteAsync(readModelId, cancellationToken).ConfigureAwait(false); return; } mssqlReadModel = readModel as IMssqlReadModel; if (mssqlReadModel != null) { mssqlReadModel.UpdatedTime = DateTimeOffset.Now; mssqlReadModel.LastAggregateSequenceNumber = (int)readModelEnvelope.Version.GetValueOrDefault(); } else { SetVersion(readModel, (int?)readModelEnvelope.Version); } var sql = isNew ? _readModelSqlGenerator.CreateInsertSql <TReadModel>() : _readModelSqlGenerator.CreateUpdateSql <TReadModel>(); var dynamicParameters = new DynamicParameters(readModel); if (originalVersion.HasValue) { dynamicParameters.Add("_PREVIOUS_VERSION", (int)originalVersion.Value); } var rowsAffected = await _connection.ExecuteAsync( Label.Named("mssql-store-read-model", ReadModelNameLowerCase), cancellationToken, sql, dynamicParameters).ConfigureAwait(false); if (rowsAffected != 1) { throw new OptimisticConcurrencyException( $"Read model '{readModelEnvelope.ReadModelId}' updated by another"); } Log.Verbose(() => $"Updated MSSQL read model {typeof(TReadModel).PrettyPrint()} with ID '{readModelId}' to version '{readModelEnvelope.Version}'"); }