Example #1
0
        async Task <T> ISqlCommandExecutor.ExecuteQueryAsync <T>(
            IActivityMonitor monitor,
            SqlConnection connection,
            SqlTransaction transaction,
            SqlCommand cmd,
            Func <SqlCommand, CancellationToken, Task <T> > innerExecutor,
            CancellationToken cancellationToken)
        {
            Debug.Assert(connection != null && connection.State == System.Data.ConnectionState.Open);
            DateTime start      = DateTime.UtcNow;
            int      retryCount = 0;
            List <SqlDetailedException> previous = null;
            T result;

            for (; ;)
            {
                SqlDetailedException e = null;
                try
                {
                    cmd.Connection  = connection;
                    cmd.Transaction = transaction;
                    OnCommandExecuting(cmd, retryCount);

                    result = await innerExecutor(cmd, cancellationToken).ConfigureAwait(false);

                    break;
                }
                catch (IOException ex)
                {
                    e = SqlDetailedException.Create(cmd, ex, retryCount++);
                }
                catch (SqlException ex)
                {
                    e = SqlDetailedException.Create(cmd, ex, retryCount++);
                }
                catch (Exception ex)
                {
                    Monitor.Fatal(ex);
                    throw;
                }
                Debug.Assert(e != null);
                Monitor.Error(e);
                if (previous == null)
                {
                    previous = new List <SqlDetailedException>();
                }
                TimeSpan retry = OnCommandError(cmd, connection, e, previous, start);
                if (retry.Ticks < 0 ||
                    retry == TimeSpan.MaxValue ||
                    previous.Count > 1000)
                {
                    throw e;
                }
                previous.Add(e);
                await Task.Delay(retry).ConfigureAwait(false);
            }
            OnCommandExecuted(cmd, retryCount, result);
            return(result);
        }