/// <summary> /// Starts new transaction asynchronously for current connection with default isolation level. If connection already has transaction, it will be rolled back. /// </summary> /// <param name="cancellationToken">Asynchronous operation cancellation token.</param> /// <returns>Database transaction object.</returns> public virtual async Task <DataConnectionTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default) { await EnsureConnectionAsync(cancellationToken).ConfigureAwait(Common.Configuration.ContinueOnCapturedContext); // If transaction is open, we dispose it, it will rollback all changes. // if (TransactionAsync != null) { await TransactionAsync.DisposeAsync().ConfigureAwait(Common.Configuration.ContinueOnCapturedContext); } // Create new transaction object. // TransactionAsync = await _connection !.BeginTransactionAsync(cancellationToken).ConfigureAwait(Common.Configuration.ContinueOnCapturedContext); _closeTransaction = true; // If the active command exists. // if (_command != null) { _command.Transaction = Transaction; } return(new DataConnectionTransaction(this)); }
/// <summary> /// Closes and dispose associated underlying database transaction/connection asynchronously. /// </summary> /// <returns>Asynchronous operation completion task.</returns> public virtual async Task CloseAsync() { OnClosing?.Invoke(this, EventArgs.Empty); DisposeCommand(); if (TransactionAsync != null && _closeTransaction) { await TransactionAsync.DisposeAsync().ConfigureAwait(Common.Configuration.ContinueOnCapturedContext); TransactionAsync = null; } if (_connection != null) { if (_disposeConnection) { await _connection.DisposeAsync().ConfigureAwait(Common.Configuration.ContinueOnCapturedContext); _connection = null; } else if (_closeConnection) { await _connection.CloseAsync().ConfigureAwait(Common.Configuration.ContinueOnCapturedContext); } } OnClosed?.Invoke(this, EventArgs.Empty); }
/// <summary> /// Rollbacks started (if any) transaction, associated with connection. /// If underlying provider doesn't support asynchonous commit, it will be performed synchonously. /// </summary> /// <param name="cancellationToken">Asynchronous operation cancellation token.</param> /// <returns>Asynchronous operation completion task.</returns> public virtual async Task RollbackTransactionAsync(CancellationToken cancellationToken = default) { if (TransactionAsync != null) { await TransactionAsync.RollbackAsync(cancellationToken).ConfigureAwait(Common.Configuration.ContinueOnCapturedContext); if (_closeTransaction) { await TransactionAsync.DisposeAsync().ConfigureAwait(Common.Configuration.ContinueOnCapturedContext); TransactionAsync = null; if (_command != null) { _command.Transaction = null; } } } }
/// <summary> /// Starts new transaction asynchronously for current connection with specified isolation level. If connection already have transaction, it will be rolled back. /// </summary> /// <param name="isolationLevel">Transaction isolation level.</param> /// <param name="cancellationToken">Asynchronous operation cancellation token.</param> /// <returns>Database transaction object.</returns> public virtual async Task <DataConnectionTransaction> BeginTransactionAsync(IsolationLevel isolationLevel, CancellationToken cancellationToken = default) { if (!DataProvider.TransactionsSupported) { return(new(this)); } await EnsureConnectionAsync(cancellationToken).ConfigureAwait(Configuration.ContinueOnCapturedContext); // If transaction is open, we dispose it, it will rollback all changes. // if (TransactionAsync != null) { await TransactionAsync.DisposeAsync().ConfigureAwait(Configuration.ContinueOnCapturedContext); } var dataConnectionTransaction = await TraceActionAsync( this, TraceOperation.BeginTransaction, static il => $"BeginTransactionAsync({il})", isolationLevel, static async (dataConnection, isolationLevel, cancellationToken) => { // Create new transaction object. // dataConnection.TransactionAsync = await dataConnection._connection !.BeginTransactionAsync(isolationLevel, cancellationToken).ConfigureAwait(Configuration.ContinueOnCapturedContext); dataConnection._closeTransaction = true; // If the active command exists. // if (dataConnection._command != null) { dataConnection._command.Transaction = dataConnection.Transaction; } return(new DataConnectionTransaction(dataConnection)); }, cancellationToken) .ConfigureAwait(Configuration.ContinueOnCapturedContext); return(dataConnectionTransaction); }
/// <summary> /// Closes and dispose associated underlying database transaction/connection asynchronously. /// </summary> /// <returns>Asynchronous operation completion task.</returns> public virtual async Task CloseAsync() { if (_dataContextInterceptor != null) { await _dataContextInterceptor.OnClosingAsync(new (this)).ConfigureAwait(Configuration.ContinueOnCapturedContext); } #if NETSTANDARD2_1PLUS await DisposeCommandAsync().ConfigureAwait(Configuration.ContinueOnCapturedContext); #else DisposeCommand(); #endif if (TransactionAsync != null && _closeTransaction) { await TransactionAsync.DisposeAsync().ConfigureAwait(Configuration.ContinueOnCapturedContext); TransactionAsync = null; } if (_connection != null) { if (_disposeConnection) { await _connection.DisposeAsync().ConfigureAwait(Configuration.ContinueOnCapturedContext); _connection = null; } else if (_closeConnection) { await _connection.CloseAsync().ConfigureAwait(Configuration.ContinueOnCapturedContext); } } if (_dataContextInterceptor != null) { await _dataContextInterceptor.OnClosedAsync(new (this)).ConfigureAwait(Configuration.ContinueOnCapturedContext); } }