Exemple #1
0
        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);
            }
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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");
            }
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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}'");
        }