簡體   English   中英

不為查詢調用實體框架自定義執行策略

[英]Entity Framework custom execution strategy not being called for queries

我已經閱讀了My custom DbExecutionStrategy is not been called的問題(有更新),但不認為這是同一個問題。

我編寫了一個自定義執行策略並包含日志信息,因此我知道它何時被調用。 但是,我仍然從查詢中得到 SQL 死鎖,但沒有跡象表明正在調用我的自定義執行策略。

自定義執行策略:

using System;
using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
using System.Diagnostics;
using log4net;

namespace MyDataModel
{
    // Based on https://stackoverflow.com/questions/13159326/implementing-retry-logic-for-deadlock-exceptions
    // and https://www.codeproject.com/Tips/758469/Implementing-Connection-Resiliency-with-Entity-Fra

    public class CustomExecutionStrategy : DbExecutionStrategy
    {
        private int _totalFailures;

        public CustomExecutionStrategy()
        {
        }

        public CustomExecutionStrategy(int maxRetryCount, TimeSpan maxDelay)
            : base(maxRetryCount, maxDelay)
        {
        }

        public static string StackTrace()
        {
            var st = new StackTrace();
            var sfs = st.GetFrames();

            var result = string.Empty;

            foreach (var sf in sfs)
            {
                var method = sf.GetMethod();
                result += (string.IsNullOrEmpty(result) ? string.Empty : "->") + method.DeclaringType.Name + "." + method.Name;
            }

            return result + " ";
        }

        protected override bool ShouldRetryOn(Exception exception)
        {
            var log = LogManager.GetLogger("Logger");

            if (exception is TimeoutException)
            {
                _totalFailures++;
                log.Info($"Retrying {exception.GetType().Name} ({_totalFailures}) - {StackTrace()}");
                return true;
            }

            if (exception is SqlException sqlException)
            {
                foreach (SqlError err in sqlException.Errors)
                {
                    // Enumerate through all errors found in the exception.
                    if (Enum.IsDefined(typeof(RetryableSqlErrors), err.Number))
                    {
                        _totalFailures++;
                        log.Info($"Retrying {exception.GetType().Name}, {(RetryableSqlErrors)err.Number} ({_totalFailures}) - {StackTrace()}");
                        return true;
                    }
                }
            }

            log.Error($"Not retrying {exception.GetType().Name} - {StackTrace()}");
            return false;
        }
    }
}

設置:

using System.Data.Entity;
using MyDataModel.Extensions;

namespace MyDataModel
{
    internal class EntityFrameworkConfiguration : DbConfiguration
    {
        public EntityFrameworkConfiguration()
        {
            SetExecutionStrategy("System.Data.SqlClient",
                () => new CustomExecutionStrategy(Setting.MaxRetry, Setting.ShortWait));
        }
    }
}

並且,在 App.Config 中:

<entityFramework codeConfigurationType="MyDataModel.EntityFrameworkConfiguration, MyDataModel">
.
.
.
</entityFramework>

以下是一些日志摘錄:

2020-08-11 04:09:15,047 [54] [26390536] ERROR MyDataModel.CustomExecutionStrategy - Not retrying SqlException - <>c__DisplayClass61_1.<FixItemAndRetry>b__1->BaseEntity.FixItemAndRetry...
2020-08-11 04:12:02,510 [52] [26557999] ERROR MyDataModel.CustomExecutionStrategy - Not retrying SqlException - <>c__DisplayClass61_1.<FixItemAndRetry>b__1->BaseEntity.FixItemAndRetry...
2020-08-11 11:09:53,350 [29] [3010774] INFO  MyDataModel.CustomExecutionStrategy - Retrying SqlException, DeadlockVictim (1) - Invoice..ctor->SyncInvoiceWithPayment.Start...
2020-08-11 11:56:12,047 [3] [5789470] INFO  MyDataModel.CustomExecutionStrategy - Retrying SqlException, DeadlockVictim (1) - Invoice..ctor->D365SyncInvoiceWorker.Start...
2020-08-11 11:56:17,048 [3] [5794471] INFO  MyDataModel.CustomExecutionStrategy - Retrying SqlException, DeadlockVictim (2) - Invoice..ctor->D365SyncInvoiceWorker.Start...
2020-08-11 14:16:20,111 [25] [3930388] INFO  MyDataModel.CustomExecutionStrategy - Retrying SqlException, DeadlockVictim (1) - Invoice..ctor->SyncInvoiceWithPayment.Start...
2020-08-11 14:16:25,110 [25] [3935386] INFO  MyDataModel.CustomExecutionStrategy - Retrying SqlException, DeadlockVictim (2) - Invoice..ctor->SyncInvoiceWithPayment.Start...
2020-08-11 14:40:35,089 [13] [5385366] INFO  MyDataModel.CustomExecutionStrategy - Retrying SqlException, DeadlockVictim (1) - Invoice..ctor->SyncInvoiceWithPayment.Start...
2020-08-11 14:40:40,089 [13] [5390365] INFO  MyDataModel.CustomExecutionStrategy - Retrying SqlException, DeadlockVictim (2) - Invoice..ctor->SyncInvoiceWithPayment.Start...
2020-08-11 14:58:51,459 [20] [6481736] INFO  MyDataModel.CustomExecutionStrategy - Retrying SqlException, DeadlockVictim (1) - Invoice..ctor->SyncInvoiceWithPayment.Start...
2020-08-11 14:58:53,958 [20] [6484234] INFO  MyDataModel.CustomExecutionStrategy - Retrying SqlException, DeadlockVictim (2) - Invoice..ctor->SyncInvoiceWithPayment.Start...

所以我知道正在調用自定義執行策略並且正在重試一些死鎖。

但也從日志中,我有:

2020-08-11 11:09:46,783 [26] [3004206] INFO  Utility.Settlement - Getting invoice lines
2020-08-11 11:09:48,352 [26] [3005775] ERROR Utility.Settlement - Stl: <N0675833635639> Save Failed !
Error: An error occurred while reading from the store provider's data reader. See the inner exception for details.
InnerError: Transaction (Process ID 409) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

從代碼和解釋錯誤消息來看,當嘗試從數據庫中查詢記錄時會發生這種情況。

如何攔截 EF6(版本 6.4.4)查詢並讓它重試 SQL 死鎖?

也許您超出了 MaxRetry 的設置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM