Exemple #1
0
        private static void CheckArguments(IScopedTransactionalDatabase database, Type dataType, object data)
        {
            if (database == null)
            {
                throw new ArgumentNullException(nameof(database));
            }

            if (dataType == null)
            {
                throw new ArgumentNullException(nameof(dataType));
            }

            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            if (dataType.IsValueType)
            {
                throw new ArgumentException("The argument must be a reference type.", nameof(dataType));
            }

            if (!dataType.IsAssignableFrom(data.GetType()))
            {
                throw new ArgumentException($"The specified data must be of type '{dataType.FullName}' or an assignable type.");
            }
        }
Exemple #2
0
        public static Task RemoveAsync(this IScopedTransactionalDatabase database,
                                       Type dataType,
                                       object data,
                                       CancellationToken cancellation = default)
        {
            CheckArguments(database, dataType, data);

            return(GetExtension(database).RemoveAsync(dataType, data, cancellation));
        }
Exemple #3
0
        private static TransactionalDataStoreExt GetExtension(IScopedTransactionalDatabase database)
        {
            Assert(database != null);

            var result = _extensions.GetOrCreateValue(database);

            Assert(result != null);

            result.Initialize(database);

            return(result);
        }
Exemple #4
0
            public void Initialize(IScopedTransactionalDatabase database)
            {
                // Volatile read op
                if (_database != null)
                {
                    return;
                }

                // Write _dataStore only if there is no data store present currently.
                var current = Interlocked.CompareExchange(ref _database, database, null);

                // If there was a data store present, it must be the same than the one, we wanted to write.
                Assert(current == null || ReferenceEquals(current, database));
            }
Exemple #5
0
        public static Task RemoveAsync(this IScopedTransactionalDatabase database,
                                       object data,
                                       CancellationToken cancellation = default)
        {
            if (database == null)
            {
                throw new ArgumentNullException(nameof(database));
            }

            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            if (data is ValueType)
            {
                throw new ArgumentException("The argument must be a reference type.", nameof(data));
            }

            return(GetExtension(database).RemoveAsync(data.GetType(), data, cancellation));
        }
Exemple #6
0
            public async Task <bool> WriteToDatabaseAsync(IScopedTransactionalDatabase transactionalDatabase, CancellationToken cancellation)
            {
                // Write touched target metadata to database
                foreach (var(originalMetadata, touchedMetadata) in _targetMetadataCache.Values.Where(p => p.Touched))
                {
                    var comparandMetdata = await transactionalDatabase.GetAsync <ProjectionTargetMetadata>(p => p.Id == (originalMetadata ?? touchedMetadata).Id).FirstOrDefault();

                    if (!MatchesByRevision(originalMetadata, comparandMetdata))
                    {
                        return(false);
                    }

                    if (touchedMetadata == null)
                    {
                        Assert(originalMetadata != null);

                        await transactionalDatabase.RemoveAsync(originalMetadata, cancellation);
                    }
                    else
                    {
                        touchedMetadata.MetadataRevision = originalMetadata?.MetadataRevision ?? 1;

                        await transactionalDatabase.StoreAsync(touchedMetadata, cancellation);
                    }
                }

                // TODO: Do we have to check whether the targets were updated concurrently?

                foreach (var targetToUpdate in _targetsToUpdate)
                {
                    await transactionalDatabase.StoreAsync(targetToUpdate, cancellation);
                }

                foreach (var targetToDelete in _targetsToDelete)
                {
                    await transactionalDatabase.RemoveAsync(targetToDelete, cancellation);
                }

                return(true);
            }
Exemple #7
0
        private static async Task <(long bankAccountNo1, long bankAccountNo2)> CreateBankAccountsAsync(IScopedTransactionalDatabase transactionalStore)
        {
            _ba1AmountComparand = Rnd.Next();
            _ba2AmountComparand = Rnd.Next();

            var bankAccount1 = new BankAccount {
                Id = 1, Amount = _ba1AmountComparand
            };
            var bankAccount2 = new BankAccount {
                Id = 2, Amount = _ba2AmountComparand
            };

            try
            {
                await transactionalStore.StoreAsync(bankAccount1);

                await transactionalStore.StoreAsync(bankAccount2);

                await transactionalStore.TryCommitAsync();
            }
            catch
            {
                await transactionalStore.RollbackAsync();

                throw;
            }

            return(bankAccount1.Id, bankAccount2.Id);
        }
Exemple #8
0
        private static async Task OutputAsync(long bankAccountNo1, long bankAccountNo2, IScopedTransactionalDatabase transactionalStore)
        {
            BankAccount bankAccount1, bankAccount2;

            try
            {
                bankAccount1 = await transactionalStore.GetAsync <BankAccount>(p => p.Id == bankAccountNo1).FirstOrDefault();

                bankAccount2 = await transactionalStore.GetAsync <BankAccount>(p => p.Id == bankAccountNo2).FirstOrDefault();

                await transactionalStore.TryCommitAsync();
            }
            catch
            {
                await transactionalStore.RollbackAsync();

                throw;
            }

            await Console.Out.WriteLineAsync($"Account1 amount: {bankAccount1.Amount} should be {_ba1AmountComparand}");

            await Console.Out.WriteLineAsync($"Account2 amount: {bankAccount2.Amount} should be {_ba2AmountComparand}");

            await Console.Out.WriteLineAsync();

            await Console.Out.WriteLineAsync(bankAccount1.Amount == _ba1AmountComparand && bankAccount2.Amount == _ba2AmountComparand? "OK" : "NOT OK");
        }