Example #1
0
        public async Task SingleCommit(DbCommand command, CancellationToken cancellation)
        {
            NpgsqlTransaction tx = null;

            try
            {
                tx = _connection.BeginTransaction();
                command.Connection = _connection;

                await command.ExecuteNonQueryAsync(cancellation).ConfigureAwait(false);

                await tx.CommitAsync(cancellation).ConfigureAwait(false);
            }
            catch (Exception)
            {
                if (tx != null)
                {
                    await tx.RollbackAsync(cancellation).ConfigureAwait(false);
                }

                // Let the caller deal with retries
                await reopenConnectionIfNecessary(cancellation).ConfigureAwait(false);

                throw;
            }
            finally
            {
                tx?.SafeDispose();
            }
        }
Example #2
0
        private async Task ProcessFailureAsync <TEntity>(
            SqlOperation operation,
            FailureStrategies currentFailureStrategy,
            Exception ex,
            NpgsqlTransaction transaction,
            ICollection <TEntity> operatedElements,
            ICollection <TEntity> notOperatedElements,
            ICollection <TEntity> problemElements,
            CancellationToken cancellationToken) where TEntity : class
        {
            if (ex == null)
            {
                throw new ArgumentNullException(nameof(ex));
            }

            _logger.LogError(ex, "Bulk command execution failed");

            if (transaction != null)
            {
                await transaction.RollbackAsync(cancellationToken);
            }

            if (currentFailureStrategy == FailureStrategies.StopEverything ||
                currentFailureStrategy == FailureStrategies.StopEverythingAndRollback)
            {
                throw new SqlBulkExecutionException <TEntity>(ex, operation, currentFailureStrategy, problemElements, notOperatedElements, operatedElements);
            }
        }
        private async Task DeleteStreamInternal(
            PostgresqlStreamId streamId,
            int expectedVersion,
            NpgsqlTransaction transaction,
            CancellationToken cancellationToken)
        {
            using (var command = BuildFunctionCommand(
                       _schema.DeleteStream,
                       transaction,
                       Parameters.StreamId(streamId),
                       Parameters.ExpectedVersion(expectedVersion),
                       Parameters.CreatedUtc(_settings.GetUtcNow?.Invoke()),
                       Parameters.DeletedStreamId,
                       Parameters.DeletedStreamIdOriginal,
                       Parameters.DeletedStreamMessage(streamId)))
            {
                try
                {
                    await command.ExecuteNonQueryAsync(cancellationToken).NotOnCapturedContext();
                }
                catch (PostgresException ex) when(ex.IsWrongExpectedVersion())
                {
                    await transaction.RollbackAsync(cancellationToken).NotOnCapturedContext();

                    throw new WrongExpectedVersionException(
                              ErrorMessages.DeleteStreamFailedWrongExpectedVersion(streamId.IdOriginal, expectedVersion),
                              streamId.IdOriginal,
                              expectedVersion,
                              ex);
                }
            }
        }
Example #4
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="connection"></param>
        /// <param name="executeAsync"></param>
        /// <param name="transaction"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private static async Task <TResult> TransactionalExecuteAsync <TResult>(this NpgsqlConnection connection,
                                                                                Func <Task <TResult> > executeAsync,
                                                                                NpgsqlTransaction transaction,
                                                                                CancellationToken cancellationToken = default)
        {
            // Variables
            var result         = default(TResult);
            var hasTransaction = transaction != null;

            // Open
            await connection.EnsureOpenAsync(cancellationToken);

            // Ensure transaction
            if (hasTransaction == false)
            {
#if NET5_0
                transaction = await connection.BeginTransactionAsync(cancellationToken);
#else
                transaction = connection.BeginTransaction();
#endif
            }

            try
            {
                // Execute
                if (executeAsync != null)
                {
                    result = await executeAsync();
                }

                // Commit
                if (hasTransaction == false)
                {
                    await transaction.CommitAsync(cancellationToken);
                }
            }
            catch
            {
                // Rollback
                if (hasTransaction == false)
                {
                    await transaction.RollbackAsync(cancellationToken);
                }

                // Throw
                throw;
            }
            finally
            {
                // Dispose
                if (hasTransaction == false)
                {
                    await transaction.DisposeAsync();
                }
            }

            // Return
            return(result);
        }
Example #5
0
        public Task RollbackAsync(CancellationToken token)
        {
            if (_options.OwnsTransactionLifecycle)
            {
                return(Transaction.RollbackAsync(token));
            }

            return(Task.CompletedTask);
        }
Example #6
0
        public static async Task <bool> ExecTransactionAsync(List <string> sqls, string connection = null)
        {
            var connString = GetConnection(connection);

            bool result = false;

            try
            {
                using (var conn = new NpgsqlConnection(connString))
                {
                    await conn.OpenAsync();

                    NpgsqlTransaction tran = conn.BeginTransaction();

                    try
                    {
                        foreach (var sql in sqls)
                        {
                            using (var cmd = new NpgsqlCommand())
                            {
                                cmd.Connection  = conn;
                                cmd.CommandText = sql;
                                result          = await cmd.ExecuteNonQueryAsync() > 0;
                            }
                        }
                    }
                    catch (Exception ex0)
                    {
                        Log.WriteLog("ERROR-DB:" + ex0.Message);
                        result = false;
                    }
                    finally
                    {
                        if (result)
                        {
                            await tran.CommitAsync();
                        }
                        else
                        {
                            await tran.RollbackAsync();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.WriteLog("ERROR-DB:" + ex.Message);
            }

            return(result);
        }
Example #7
0
        public async Task <int> WriteAsync(IEnumerable <AppMetric> appMetrics)
        {
            int affectedRows = 0;

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

            if (appMetrics.Count() == 0)
            {
                return(affectedRows);
            }

            using (NpgsqlConnection conn = await OpenConnectionAsync())
                using (NpgsqlTransaction tx = conn.BeginTransaction())
                    using (NpgsqlCommand upsertCmd = new NpgsqlCommand(mMetricsUpsertSql, conn, tx))
                    {
                        try
                        {
                            NpgsqlParameter pMetricId = upsertCmd.Parameters.Add("m_id",
                                                                                 NpgsqlDbType.Varchar);
                            NpgsqlParameter pMetricCategory = upsertCmd.Parameters.Add("m_category",
                                                                                       NpgsqlDbType.Varchar);
                            NpgsqlParameter pMetricValue = upsertCmd.Parameters.Add("m_value",
                                                                                    NpgsqlDbType.Bigint);

                            await upsertCmd.PrepareAsync();

                            foreach (AppMetric m in appMetrics)
                            {
                                pMetricId.Value       = m.Id.ValueId;
                                pMetricCategory.Value = m.Id.ValueCategory;
                                pMetricValue.Value    = m.Value;

                                affectedRows += await upsertCmd.ExecuteNonQueryAsync();
                            }

                            await tx.CommitAsync();
                        }
                        catch (Exception)
                        {
                            await tx.RollbackAsync();

                            throw;
                        }
                    }

            return(affectedRows);
        }
        public bool RollbackTransaction()
        {
            try
            {
                trans.RollbackAsync(); // 异步回滚
                isRollback = true;

                return(true);
            }
            catch (Exception ex)
            {
                LastError = ex.Message;
                Logger.WriteLogExcept(LogTitle, ex);

                return(false);
            }
            finally
            {
                trans = null;
            }
        }
Example #9
0
		protected async Task<T> WithConnection<T> (Func<IDbConnection, IDbTransaction, Task<T>> f)
		{
			T result = default(T);
			using (NpgsqlConnection sqlConnection = new NpgsqlConnection(_settings.Value.ConnectionString))
			{
				await sqlConnection.OpenAsync();
				using (NpgsqlTransaction transaction = sqlConnection.BeginTransaction())
				{
					try
					{
						result = await f(sqlConnection, transaction);
						transaction.Commit();
					}
					catch (Exception ex)
					{
						_logger.LogError(ex.Message, ex);
						await transaction.RollbackAsync();
						throw;
					}
				}

				return result;
			}
		}
        private async Task <object> ExecStoredProcedureAsync(ExecType execType)
        {
            object            result      = null;
            NpgsqlTransaction transaction = null;

            using (_command.Connection)
            {
                try
                {
                    await InitCommandAsync();

                    transaction = _command.Connection.BeginTransaction();

                    using (_command)
                    {
                        if (_needPreparation)
                        {
                            await _command.PrepareAsync();
                        }

                        if (_needReloadTypes)
                        {
                            _command.Connection?.ReloadTypes();
                        }

                        switch (execType)
                        {
                        case ExecType.NonQuery:
                        {
                            await _command.ExecuteNonQueryAsync();

                            break;
                        }

                        case ExecType.Reader:
                        {
                            await _command.ExecuteNonQueryAsync();

                            var fetchAllCommand = new NpgsqlCommand($"FETCH ALL IN \"{_refCursorName}\";", _command.Connection);
                            fetchAllCommand.Transaction = transaction;

                            var reader = await fetchAllCommand.ExecuteReaderAsync();

                            using (reader)
                            {
                                do
                                {
                                    while (await reader.ReadAsync())
                                    {
                                        _dataReaderAction?.Invoke(reader);
                                    }
                                }while (await reader.NextResultAsync());
                            }

                            break;
                        }

                        case ExecType.Scalar:
                        {
                            await _command.ExecuteNonQueryAsync();

                            var fetchAllCommand = new NpgsqlCommand($"FETCH ALL IN \"{_refCursorName}\";", _command.Connection);
                            fetchAllCommand.Transaction = transaction;

                            result = await fetchAllCommand.ExecuteScalarAsync();

                            break;
                        }
                        }
                    }

                    transaction.Commit();
                }
                catch (PostgresException ex)
                {
                    transaction?.RollbackAsync();
                    ProcessException(ex);
                }
            }

            return(result);
        }
        public async Task <int> WriteAsync(IEnumerable <TaskPerformanceStats> executionTimeInfoBatch)
        {
            int affectedRows = 0;

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

            if (executionTimeInfoBatch.Count() == 0)
            {
                return(0);
            }

            using (NpgsqlConnection conn = await OpenConnectionAsync())
                using (NpgsqlTransaction tx = conn.BeginTransaction())
                    using (NpgsqlCommand upsertCmd = new NpgsqlCommand(mPerfMonInfoUpsertSql, conn, tx))
                    {
                        try
                        {
                            NpgsqlParameter pPayloadType = upsertCmd.Parameters
                                                           .Add("payload_type", NpgsqlDbType.Varchar);
                            NpgsqlParameter pNExecutionCycles = upsertCmd.Parameters
                                                                .Add("n_execution_cycles", NpgsqlDbType.Bigint);
                            NpgsqlParameter pLastExecutionTime = upsertCmd.Parameters
                                                                 .Add("last_execution_time", NpgsqlDbType.Bigint);
                            NpgsqlParameter pAvgExecutionTime = upsertCmd.Parameters
                                                                .Add("avg_execution_time", NpgsqlDbType.Bigint);
                            NpgsqlParameter pFastestExecutionTime = upsertCmd.Parameters
                                                                    .Add("fastest_execution_time", NpgsqlDbType.Bigint);
                            NpgsqlParameter pLongestExecutionTime = upsertCmd.Parameters
                                                                    .Add("longest_execution_time", NpgsqlDbType.Bigint);
                            NpgsqlParameter pTotalExecutionTime = upsertCmd.Parameters
                                                                  .Add("total_execution_time", NpgsqlDbType.Bigint);

                            await upsertCmd.PrepareAsync();

                            foreach (TaskPerformanceStats s in executionTimeInfoBatch)
                            {
                                pPayloadType.Value          = s.PayloadType;
                                pNExecutionCycles.Value     = 1;
                                pLastExecutionTime.Value    = s.DurationMilliseconds;
                                pAvgExecutionTime.Value     = s.DurationMilliseconds;
                                pFastestExecutionTime.Value = s.DurationMilliseconds;
                                pLongestExecutionTime.Value = s.DurationMilliseconds;
                                pTotalExecutionTime.Value   = s.DurationMilliseconds;

                                affectedRows += await upsertCmd.ExecuteNonQueryAsync();
                            }

                            await tx.CommitAsync();
                        }
                        catch (Exception)
                        {
                            await tx.RollbackAsync();

                            throw;
                        }
                    }

            return(affectedRows);
        }
        public async Task <IQueuedTaskToken> DequeueAsync(params string[] selectTaskTypes)
        {
            NpgsqlConnection          conn               = null;
            QueuedTask                dequeuedTask       = null;
            QueuedTaskResult          dequeuedTaskResult = null;
            PostgreSqlQueuedTaskToken dequeuedTaskToken  = null;

            MonotonicTimestamp startDequeue;
            DateTimeOffset     refNow = mTimestampProvider.GetNow();

            CheckNotDisposedOrThrow();

            try
            {
                mLogger.DebugFormat("Begin dequeue task. Looking for types: {0}.",
                                    string.Join <string>(",", selectTaskTypes));

                startDequeue = MonotonicTimestamp
                               .Now();

                conn = await OpenQueueConnectionAsync();

                if (conn == null)
                {
                    return(null);
                }

                using (NpgsqlTransaction tx = conn.BeginTransaction(IsolationLevel.ReadCommitted))
                {
                    //1. Dequeue means that we acquire lock on a task in the queue
                    //	with the guarantee that nobody else did, and respecting
                    //	the priority and static locks (basically the task_locked_until which says
                    //	that it should not be pulled out of the queue until the
                    //	current abstract time reaches that tick value)
                    dequeuedTask = await TryDequeueTaskAsync(selectTaskTypes, refNow, conn, tx);

                    if (dequeuedTask != null)
                    {
                        //2. Mark the task as being "Processing" and pull result info
                        //	The result is stored separately and it's what allows us to remove
                        //	the task from the queue at step #2,
                        //	whils also tracking it's processing status and previous results
                        dequeuedTaskResult = await TryUpdateTaskResultAsync(dequeuedTask, conn, tx);

                        if (dequeuedTaskResult != null)
                        {
                            await tx.CommitAsync();

                            dequeuedTaskToken = new PostgreSqlQueuedTaskToken(dequeuedTask,
                                                                              dequeuedTaskResult,
                                                                              refNow);
                        }
                    }

                    if (dequeuedTaskToken != null)
                    {
                        IncrementDequeueCount(MonotonicTimestamp.Since(startDequeue));
                    }
                    else
                    {
                        await tx.RollbackAsync();
                    }
                }
            }
            finally
            {
                if (conn != null)
                {
                    await conn.CloseAsync();

                    conn.Dispose();
                }
            }

            return(dequeuedTaskToken);
        }