Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities.DurableInstancing / System / Activities / DurableInstancing / SqlCommandAsyncResult.cs / 1610140 / SqlCommandAsyncResult.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.Activities.DurableInstancing { using System.Data; using System.Data.SqlClient; using System.Globalization; using System.Linq; using System.Runtime; using System.Transactions; sealed class SqlCommandAsyncResult : AsyncResult { static readonly TimeSpan MaximumOpenTimeout = TimeSpan.FromMinutes(2); static readonly RetryErrorCode[] retryErrorCodes = { new RetryErrorCode(-2, RetryErrorOptions.RetryBeginOrEnd | RetryErrorOptions.RetryWhenTransaction), // SqlError: Timeout new RetryErrorCode(53, RetryErrorOptions.RetryBeginOrEnd | RetryErrorOptions.RetryWhenTransaction), //A network-related or instance-specific error occurred while establishing a connection to SQL Server. new RetryErrorCode(64, RetryErrorOptions.RetryBeginOrEnd | RetryErrorOptions.RetryWhenTransaction), //A transport-level error has occurred when receiving results from the server (TCP Provider, error: 0 - The specified network name is no longer available). new RetryErrorCode(121, RetryErrorOptions.RetryBeginOrEnd), // A transport-level error has occurred new RetryErrorCode(1205, RetryErrorOptions.RetryBeginOrEnd), // Deadlock new RetryErrorCode(1222, RetryErrorOptions.RetryBeginOrEnd | RetryErrorOptions.RetryWhenTransaction), // Lock Request Timeout new RetryErrorCode(3910, RetryErrorOptions.RetryOnBegin | RetryErrorOptions.RetryWhenTransaction), // Transaction context in use by another session. new RetryErrorCode(8645, RetryErrorOptions.RetryBeginOrEnd | RetryErrorOptions.RetryWhenTransaction), // A timeout occurred while waiting for memory resources new RetryErrorCode(8641, RetryErrorOptions.RetryBeginOrEnd | RetryErrorOptions.RetryWhenTransaction), // Could not perform the operation because the requested memory grant was not available new RetryErrorCode(10054, RetryErrorOptions.RetryBeginOrEnd | RetryErrorOptions.RetryWhenTransaction), // Severed tcp connection drawn from the pool new RetryErrorCode(233, RetryErrorOptions.RetryBeginOrEnd | RetryErrorOptions.RetryWhenTransaction) // Severed shared memory/named pipe connection drawn from the pool }; const int maximumRetries = 4; static AsyncCompletion onExecuteReaderCallback = new AsyncCompletion(OnExecuteReader); static AsyncCompletion onRetryCommandCallback = new AsyncCompletion(OnRetryCommand); string connectionString; DependentTransaction dependentTransaction; int retryCount; SqlCommand sqlCommand; SqlDataReader sqlDataReader; TimeoutHelper timeoutHelper; public SqlCommandAsyncResult(SqlCommand sqlCommand, string connectionString, DependentTransaction dependentTransaction, TimeSpan timeout, int retryCount, AsyncCallback callback, object state) : base(callback, state) { long openTimeout = Math.Min(timeout.Ticks, SqlCommandAsyncResult.MaximumOpenTimeout.Ticks); this.sqlCommand = sqlCommand; this.connectionString = connectionString; this.dependentTransaction = dependentTransaction; this.timeoutHelper = new TimeoutHelper(TimeSpan.FromTicks(openTimeout)); this.retryCount = retryCount; } [Flags] enum RetryErrorOptions { RetryOnBegin = 1, RetryOnEnd = 2, RetryWhenTransaction = 4, RetryBeginOrEnd = RetryOnBegin | RetryOnEnd } public static SqlDataReader End(IAsyncResult result) { SqlCommandAsyncResult SqlCommandAsyncResult = AsyncResult.End(result); return SqlCommandAsyncResult.sqlDataReader; } public void StartCommand() { StartCommandInternal(true); } static bool OnExecuteReader(IAsyncResult result) { SqlCommandAsyncResult thisPtr = (SqlCommandAsyncResult)(result.AsyncState); return thisPtr.CompleteExecuteReader(result); } static bool OnRetryCommand(IAsyncResult childPtr) { SqlCommandAsyncResult parentPtr = (SqlCommandAsyncResult)(childPtr.AsyncState); parentPtr.sqlDataReader = SqlCommandAsyncResult.End(childPtr); return true; } static bool ShouldRetryForSqlError(int error, RetryErrorOptions retryErrorOptions) { if (Transaction.Current != null) { retryErrorOptions |= RetryErrorOptions.RetryWhenTransaction; } return SqlCommandAsyncResult.retryErrorCodes.Any(x => x.ErrorCode == error && (x.RetryErrorOptions & retryErrorOptions) == retryErrorOptions); } static void StartCommandCallback(object state) { SqlCommandAsyncResult thisPtr = (SqlCommandAsyncResult) state; try { // this can throw on the [....] path - we need to signal the callback thisPtr.StartCommandInternal(false); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } if (thisPtr.sqlCommand.Connection != null) { thisPtr.sqlCommand.Connection.Close(); } thisPtr.Complete(false, e); } } bool CheckRetryCount() { return (++this.retryCount < maximumRetries); } bool CheckRetryCountAndTimer() { return (this.CheckRetryCount() && !this.HasOperationTimedOut()); } bool CompleteExecuteReader(IAsyncResult result) { bool completeSelf = true; try { this.sqlDataReader = this.sqlCommand.EndExecuteReader(result); } catch (SqlException exception) { if (TD.SqlExceptionCaughtIsEnabled()) { TD.SqlExceptionCaught(exception.Number.ToString(CultureInfo.InvariantCulture), exception.Message); } if (this.sqlDataReader != null) { this.sqlDataReader.Close(); } if (this.sqlCommand.Connection != null) { this.sqlCommand.Connection.Close(); } // If we completed [....] then any retry is done by the original caller. if (!result.CompletedSynchronously) { if (this.CheckRetryCountAndTimer() && ShouldRetryForSqlError(exception.Number, RetryErrorOptions.RetryOnEnd)) { if (this.EnqueueRetry()) { if (TD.RetryingSqlCommandDueToSqlErrorIsEnabled()) { TD.RetryingSqlCommandDueToSqlError(exception.Number.ToString(CultureInfo.InvariantCulture)); } completeSelf = false; } } } if (completeSelf) { if (this.retryCount == maximumRetries && TD.MaximumRetriesExceededForSqlCommandIsEnabled()) { TD.MaximumRetriesExceededForSqlCommand(); } throw; } } return completeSelf; } bool EnqueueRetry() { bool result = false; int delay = this.GetRetryDelay(); if (this.timeoutHelper.RemainingTime().TotalMilliseconds > delay) { this.sqlCommand.Dispose(); IOThreadTimer iott = new IOThreadTimer(StartCommandCallback, new SqlCommandAsyncResult(CloneSqlCommand(this.sqlCommand), this.connectionString, this.dependentTransaction, this.timeoutHelper.RemainingTime(), this.retryCount, this.PrepareAsyncCompletion(onRetryCommandCallback), this), false); iott.Set(delay); if (TD.QueingSqlRetryIsEnabled()) { TD.QueingSqlRetry(delay.ToString(CultureInfo.InvariantCulture)); } result = true; } return result; } static SqlCommand CloneSqlCommand(SqlCommand command) { //We do not want to use SqlCommand.Clone here because we do not want to replicate the parameters SqlCommand newCommand = new SqlCommand() { CommandType = command.CommandType, CommandText = command.CommandText, }; SqlParameter[] tempParameterList = new SqlParameter[command.Parameters.Count]; for (int i = 0; i < command.Parameters.Count; i++) { tempParameterList[i] = command.Parameters[i]; } command.Parameters.Clear(); newCommand.Parameters.AddRange(tempParameterList); return newCommand; } int GetRetryDelay() { return 1000; } bool HasOperationTimedOut() { return (this.timeoutHelper.RemainingTime() <= TimeSpan.Zero); } void StartCommandInternal(bool synchronous) { if (!this.HasOperationTimedOut()) { try { IAsyncResult result; using (this.PrepareTransactionalCall(this.dependentTransaction)) { AsyncCallback wrappedCallback = this.PrepareAsyncCompletion(onExecuteReaderCallback); this.sqlCommand.Connection = StoreUtilities.CreateConnection(this.connectionString); if (!this.HasOperationTimedOut()) { result = this.sqlCommand.BeginExecuteReader(wrappedCallback, this, CommandBehavior.CloseConnection); } else { this.sqlCommand.Connection.Close(); this.Complete(synchronous, new TimeoutException(SR.TimeoutOnSqlOperation(this.timeoutHelper.OriginalTimeout.ToString()))); return; } } if (this.CheckSyncContinue(result)) { if (this.CompleteExecuteReader(result)) { this.Complete(synchronous); } } return; } catch (SqlException exception) { if (TD.SqlExceptionCaughtIsEnabled()) { TD.SqlExceptionCaught(exception.Number.ToString(CultureInfo.InvariantCulture), exception.Message); } if (this.sqlCommand.Connection != null) { this.sqlCommand.Connection.Close(); } if (!this.CheckRetryCount() || !ShouldRetryForSqlError(exception.Number, RetryErrorOptions.RetryOnBegin)) { throw; } if (TD.RetryingSqlCommandDueToSqlErrorIsEnabled()) { TD.RetryingSqlCommandDueToSqlError(exception.Number.ToString(CultureInfo.InvariantCulture)); } } catch (InvalidOperationException) { if (!this.CheckRetryCount()) { throw; } } if (this.EnqueueRetry()) { return; } } if (this.HasOperationTimedOut()) { if (TD.TimeoutOpeningSqlConnectionIsEnabled()) { TD.TimeoutOpeningSqlConnection(this.timeoutHelper.OriginalTimeout.ToString()); } } else { if (TD.MaximumRetriesExceededForSqlCommandIsEnabled()) { TD.MaximumRetriesExceededForSqlCommand(); } } this.Complete(synchronous, new TimeoutException(SR.TimeoutOnSqlOperation(this.timeoutHelper.OriginalTimeout.ToString()))); } class RetryErrorCode { public RetryErrorCode(int code, RetryErrorOptions retryErrorOptions) { this.ErrorCode = code; this.RetryErrorOptions = retryErrorOptions; } public int ErrorCode { get; private set; } public RetryErrorOptions RetryErrorOptions { get; private set; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- PageBuildProvider.cs
- Visual3D.cs
- SignatureToken.cs
- WorkflowInlining.cs
- ExtractorMetadata.cs
- DefaultBindingPropertyAttribute.cs
- WaitForChangedResult.cs
- BitArray.cs
- InkSerializer.cs
- WorkItem.cs
- COM2ColorConverter.cs
- TextDecoration.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- DocumentSequence.cs
- WmfPlaceableFileHeader.cs
- QilInvokeEarlyBound.cs
- XmlSchemaSet.cs
- DrawingGroupDrawingContext.cs
- IntSecurity.cs
- isolationinterop.cs
- QilCloneVisitor.cs
- FixedDocumentPaginator.cs
- TreeIterator.cs
- TimerElapsedEvenArgs.cs
- ConfigurationLockCollection.cs
- XmlDocument.cs
- RuleSettings.cs
- ClientSponsor.cs
- SoapIgnoreAttribute.cs
- FileUpload.cs
- UseLicense.cs
- ServiceHostFactory.cs
- StringExpressionSet.cs
- _LazyAsyncResult.cs
- KnownColorTable.cs
- SecurityDescriptor.cs
- FixedTextBuilder.cs
- BidPrivateBase.cs
- TextRunProperties.cs
- ApplicationBuildProvider.cs
- CacheEntry.cs
- CommonProperties.cs
- JumpPath.cs
- CodeExpressionStatement.cs
- ItemsPanelTemplate.cs
- ConfigurationManagerHelperFactory.cs
- MessageTransmitTraceRecord.cs
- ExpressionEvaluator.cs
- HttpApplication.cs
- XmlSerializationGeneratedCode.cs
- ListBox.cs
- XmlWriter.cs
- QueryStringParameter.cs
- HwndHostAutomationPeer.cs
- Thickness.cs
- DelegateHelpers.Generated.cs
- ReflectionTypeLoadException.cs
- HWStack.cs
- ToolStripOverflowButton.cs
- OleDbConnectionPoolGroupProviderInfo.cs
- EditorPartCollection.cs
- DesignSurface.cs
- AppSettingsReader.cs
- CharAnimationUsingKeyFrames.cs
- XmlReflectionImporter.cs
- TimeSpanSecondsOrInfiniteConverter.cs
- FileDialogCustomPlace.cs
- wgx_commands.cs
- URLIdentityPermission.cs
- GridViewAutomationPeer.cs
- SizeConverter.cs
- PixelFormatConverter.cs
- LinkButton.cs
- FormViewInsertedEventArgs.cs
- StrongNamePublicKeyBlob.cs
- DispatcherOperation.cs
- BrowserDefinition.cs
- File.cs
- StaticSiteMapProvider.cs
- FixedPageProcessor.cs
- DataColumnMapping.cs
- UInt64Storage.cs
- DataGridViewControlCollection.cs
- FixedSOMImage.cs
- SplayTreeNode.cs
- PermissionAttributes.cs
- UnsupportedPolicyOptionsException.cs
- EndpointAddress.cs
- ObjectQuery.cs
- MatrixKeyFrameCollection.cs
- HwndProxyElementProvider.cs
- DataBindingHandlerAttribute.cs
- CellQuery.cs
- RemotingException.cs
- ProcessHostConfigUtils.cs
- TemplatedAdorner.cs
- PhysicalFontFamily.cs
- InOutArgument.cs
- tabpagecollectioneditor.cs
- ArrayTypeMismatchException.cs