public SqlTransaction BeginTransaction(IsolationLevel iso, string transactionName) { WaitForPendingReconnection(); SqlStatistics statistics = null; try { statistics = SqlStatistics.StartTimer(Statistics); SqlTransaction transaction; bool isFirstAttempt = true; do { transaction = GetOpenTdsConnection().BeginSqlTransaction(iso, transactionName, isFirstAttempt); // do not reconnect twice Debug.Assert(isFirstAttempt || !transaction.InternalTransaction.ConnectionHasBeenRestored, "Restored connection on non-first attempt"); isFirstAttempt = false; } while (transaction.InternalTransaction.ConnectionHasBeenRestored); // The GetOpenConnection line above doesn't keep a ref on the outer connection (this), // and it could be collected before the inner connection can hook it to the transaction, resulting in // a transaction with a null connection property. Use GC.KeepAlive to ensure this doesn't happen. GC.KeepAlive(this); return(transaction); } finally { SqlStatistics.StopTimer(statistics); } }
override public void Open() { if (StatisticsEnabled) { if (null == _statistics) { _statistics = new SqlStatistics(); } else { _statistics.ContinueOnNewConnection(); } } SqlStatistics statistics = null; try { statistics = SqlStatistics.StartTimer(Statistics); if (!TryOpen(null)) { throw ADP.InternalError(ADP.InternalErrorCode.SynchronousConnectReturnedPending); } } finally { SqlStatistics.StopTimer(statistics); } }
override public void Rollback() { if (IsYukonPartialZombie) { // Put something in the trace in case a customer has an issue _internalTransaction = null; // yukon zombification } else { ZombieCheck(); SqlStatistics statistics = null; try { statistics = SqlStatistics.StartTimer(Statistics); _isFromAPI = true; _internalTransaction.Rollback(); } finally { _isFromAPI = false; SqlStatistics.StopTimer(statistics); } } }
static internal void StopTimer(SqlStatistics statistics) { if (null != statistics) { statistics.ReleaseAndUpdateExecutionTimer(); } }
virtual internal SqlTransaction BeginSqlTransaction(IsolationLevel iso, string transactionName, bool shouldReconnect) { SqlStatistics statistics = null; try { statistics = SqlStatistics.StartTimer(Connection.Statistics); ValidateConnectionForExecute(null); if (HasLocalTransactionFromAPI) { throw ADP.ParallelTransactionsNotSupported(Connection); } if (iso == IsolationLevel.Unspecified) { iso = IsolationLevel.ReadCommitted; // Default to ReadCommitted if unspecified. } SqlTransaction transaction = new SqlTransaction(this, Connection, iso, AvailableInternalTransaction); transaction.InternalTransaction.RestoreBrokenConnection = shouldReconnect; ExecuteTransaction(TransactionRequest.Begin, transactionName, iso, transaction.InternalTransaction); transaction.InternalTransaction.RestoreBrokenConnection = false; return(transaction); } finally { SqlStatistics.StopTimer(statistics); } }
static internal SqlStatistics StartTimer(SqlStatistics statistics) { if ((null != statistics) && !statistics.RequestExecutionTimer()) { // we're re-entrant -- don't bother. statistics = null; } return(statistics); }
internal void Retry(Task <DbConnectionInternal> retryTask) { _registration.Dispose(); try { SqlStatistics statistics = null; try { statistics = SqlStatistics.StartTimer(_parent.Statistics); if (retryTask.IsFaulted) { Exception e = retryTask.Exception.InnerException; _parent.CloseInnerConnection(); _parent._currentCompletion = null; _result.SetException(retryTask.Exception.InnerException); } else if (retryTask.IsCanceled) { _parent.CloseInnerConnection(); _parent._currentCompletion = null; _result.SetCanceled(); } else { bool result; // protect continuation from races with close and cancel lock (_parent.InnerConnection) { result = _parent.TryOpen(_retry); } if (result) { _parent._currentCompletion = null; _result.SetResult(null); } else { _parent.CloseInnerConnection(); _parent._currentCompletion = null; _result.SetException(ADP.ExceptionWithStackTrace(ADP.InternalError(ADP.InternalErrorCode.CompletedConnectReturnedPending))); } } } finally { SqlStatistics.StopTimer(statistics); } } catch (Exception e) { _parent.CloseInnerConnection(); _parent._currentCompletion = null; _result.SetException(e); } }
override public void ChangeDatabase(string database) { SqlStatistics statistics = null; RepairInnerConnection(); try { statistics = SqlStatistics.StartTimer(Statistics); InnerConnection.ChangeDatabase(database); } finally { SqlStatistics.StopTimer(statistics); } }
public void Save(string savePointName) { ZombieCheck(); SqlStatistics statistics = null; try { statistics = SqlStatistics.StartTimer(Statistics); _internalTransaction.Save(savePointName); } finally { SqlStatistics.StopTimer(statistics); } }
private bool TryOpen(TaskCompletionSource <DbConnectionInternal> retry) { SqlConnectionString connectionOptions = (SqlConnectionString)ConnectionOptions; _applyTransientFaultHandling = (retry == null && connectionOptions != null && connectionOptions.ConnectRetryCount > 0); if (ForceNewConnection) { if (!InnerConnection.TryReplaceConnection(this, ConnectionFactory, retry, UserConnectionOptions)) { return(false); } } else { if (!InnerConnection.TryOpenConnection(this, ConnectionFactory, retry, UserConnectionOptions)) { return(false); } } // does not require GC.KeepAlive(this) because of OnStateChange var tdsInnerConnection = (InnerConnection as SqlInternalConnectionTds); Debug.Assert(tdsInnerConnection.Parser != null, "Where's the parser?"); if (!tdsInnerConnection.ConnectionOptions.Pooling) { // For non-pooled connections, we need to make sure that the finalizer does actually run to avoid leaking SNI handles GC.ReRegisterForFinalize(this); } if (StatisticsEnabled) { ADP.TimerCurrent(out _statistics._openTimestamp); tdsInnerConnection.Parser.Statistics = _statistics; } else { tdsInnerConnection.Parser.Statistics = null; _statistics = null; // in case of previous Open/Close/reset_CollectStats sequence } return(true); }
public void Rollback(string transactionName) { ZombieCheck(); SqlStatistics statistics = null; try { statistics = SqlStatistics.StartTimer(Statistics); _isFromAPI = true; _internalTransaction.Rollback(transactionName); } finally { _isFromAPI = false; SqlStatistics.StopTimer(statistics); } }
//////////////////////////////////////////////////////////////////////////////////////// // PUBLIC METHODS //////////////////////////////////////////////////////////////////////////////////////// override public void Commit() { ZombieCheck(); SqlStatistics statistics = null; try { statistics = SqlStatistics.StartTimer(Statistics); _isFromAPI = true; _internalTransaction.Commit(); } finally { _isFromAPI = false; SqlStatistics.StopTimer(statistics); } }
override public void Close() { SqlStatistics statistics = null; try { statistics = SqlStatistics.StartTimer(Statistics); Task reconnectTask = _currentReconnectionTask; if (reconnectTask != null && !reconnectTask.IsCompleted) { CancellationTokenSource cts = _reconnectionCancellationSource; if (cts != null) { cts.Cancel(); } AsyncHelper.WaitForCompletion(reconnectTask, 0, null, rethrowExceptions: false); // we do not need to deal with possible exceptions in reconnection if (State != ConnectionState.Open) { // if we cancelled before the connection was opened OnStateChange(DbConnectionInternal.StateChangeClosed); } } CancelOpenAndWait(); CloseInnerConnection(); GC.SuppressFinalize(this); if (null != Statistics) { ADP.TimerCurrent(out _statistics._closeTimestamp); } } finally { SqlStatistics.StopTimer(statistics); } }
public override Task OpenAsync(CancellationToken cancellationToken) { if (StatisticsEnabled) { if (null == _statistics) { _statistics = new SqlStatistics(); } else { _statistics.ContinueOnNewConnection(); } } SqlStatistics statistics = null; try { statistics = SqlStatistics.StartTimer(Statistics); TaskCompletionSource <DbConnectionInternal> completion = new TaskCompletionSource <DbConnectionInternal>(); TaskCompletionSource <object> result = new TaskCompletionSource <object>(); if (cancellationToken.IsCancellationRequested) { result.SetCanceled(); return(result.Task); } bool completed; try { completed = TryOpen(completion); } catch (Exception e) { result.SetException(e); return(result.Task); } if (completed) { result.SetResult(null); } else { CancellationTokenRegistration registration = new CancellationTokenRegistration(); if (cancellationToken.CanBeCanceled) { registration = cancellationToken.Register(() => completion.TrySetCanceled()); } OpenAsyncRetry retry = new OpenAsyncRetry(this, completion, result, registration); _currentCompletion = new Tuple <TaskCompletionSource <DbConnectionInternal>, Task>(completion, result.Task); completion.Task.ContinueWith(retry.Retry, TaskScheduler.Default); return(result.Task); } return(result.Task); } finally { SqlStatistics.StopTimer(statistics); } }