コード例 #1
0
        public static void InvokeWithConcurrencyRetryAllowNested(
            Action <TransactionScope> action,
            TransactionScopeOption transactionScopeOption = TransactionScopeOption.Required,
            int maxRetries   = 3,
            TimeSpan?timeout = null)
        //TransactionScopeAsyncFlowOption transactionScopeAsyncFlowOption = TransactionScopeAsyncFlowOption.Suppress) // .NET 4.5.1 feature
        {
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            // If this is an inner transaction, the outer transaction is responsible for the retry logic
            if (transactionScopeOption == TransactionScopeOption.Required && Transaction.Current != null)
            {
                using (var scope = CreateSerializable(transactionScopeOption, timeout /*, transactionScopeAsyncFlowOption*/))
                {
                    action(scope);
                }
            }
            else
            {
                var attempt = 0;

                ActionUtils.RetryAction(
                    () =>
                {
                    attempt++;
                    using (var scope = CreateSerializable(transactionScopeOption, timeout /*, transactionScopeAsyncFlowOption*/))
                    {
                        action(scope);
                    }
                },
                    TimeSpan.MaxValue,
                    ex =>
                {
                    if (ex is TransactionAbortedException &&
                        ex.InnerException is ConcurrencyException)
                    {
                        var msg = string.Format("Transaction concurrency fault occured. Attempt: {0}/{1}", attempt, maxRetries);
                        Log.Warn(msg, ex);

                        if (attempt < maxRetries)
                        {
                            return(true);
                        }
                    }

                    return(false);
                });
            }
        }
コード例 #2
0
        public static void InvokeWithConcurrencyRetry(
            Action <TransactionScope> action,
            TransactionScopeOption transactionScopeOption = TransactionScopeOption.Required,
            int maxRetries   = 3,
            TimeSpan?timeout = null)
        //TransactionScopeAsyncFlowOption transactionScopeAsyncFlowOption = TransactionScopeAsyncFlowOption.Suppress) // .NET 4.5.1 feature
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            if (transactionScopeOption == TransactionScopeOption.Required && Transaction.Current != null)
            {
                throw new TransactionException("Error, ambient transaction already exists. Retry must occur on outer or new transaction scope");
            }

            var attempt = 0;

            ActionUtils.RetryAction(
                () =>
            {
                attempt++;
                using (var scope = CreateSerializable(transactionScopeOption, timeout /*, transactionScopeAsyncFlowOption*/))
                {
                    action(scope);
                }
            },
                TimeSpan.MaxValue,
                ex =>
            {
                if (ex is TransactionAbortedException && ex.InnerException is ConcurrencyException)
                {
                    Log.WarnException($"Transaction concurrency fault occured. Attempt: {attempt}/{maxRetries}", ex);

                    if (attempt < maxRetries)
                    {
                        return(true);
                    }
                }

                return(false);
            });
        }