实体框架自定义执行策略未调用查询

问题描述

我已经在My custom DbExecutionStrategy is not being 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 的设置。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...