gpt4 book ai didi

c# - 我的自定义 DbExecutionStrategy 没有被调用

转载 作者:行者123 更新时间:2023-12-02 11:21:28 26 4
gpt4 key购买 nike

我最初的问题是我在更新 SQL 数据库时经常遇到死锁。通过一点点研究,我发现我能够定义一个自定义 DbConfiguration 和一个 DbExecutionStrategy,它指示 Entity Framework 在 x 毫秒和 y 次后出现某些错误后自动重试。伟大的!

因此,请按照 https://msdn.microsoft.com/en-us/data/jj680699 上的指南进行操作,我构建了我正在使用的自定义 DbConfiguration,但关联的 DbExecutionStrategy 似乎被忽略了。

最初,我的整个 DbConfiguration 都被忽略了,但我发现这是因为我在 app.config 中引用了它,并使用 DbConfigurationType 属性 [DbConfigurationType(typeof(MyConfiguration))] 装饰了我的实体构造函数。现在我只使用 app.config,至少我的自定义配置正在被调用。

以最简单的形式,我的自定义配置如下所示:

public class MyConfiguration : DbConfiguration
{
public MyConfiguration()
{
System.Windows.MessageBox.Show("Hey! Here I am!"); //I threw this in just to check that I was calling the constructor. Simple breakpoints don't seem to work here.
SetExecutionStrategy("System.Data.SqlClient", () => new MyExecutionStrategy(3, TimeSpan.FromMilliseconds(500)));
}
}

我的自定义 DbConfiguration 在我的 app.config 中被引用,如下所示:
<entityFramework codeConfigurationType="MyDataLayer.MyConfiguration, MyDataLayer">
...
</entityFramework>

我的自定义 DbExecutionStrategy 是这样构建的:
private class MyExecutionStrategy : DbExecutionStrategy
{
public MyExecutionStrategy() : this(3, TimeSpan.FromSeconds(2))
{
System.Windows.MessageBox.Show($"MyExecutionStrategy instantiated through default constructor.");
}

public MyExecutionStrategy(int maxRetryCount, TimeSpan maxDelay) : base(maxRetryCount, maxDelay)
{
System.Windows.MessageBox.Show($"MyExecutionStrategy instantiated through parametered constructor.");
}

protected override bool ShouldRetryOn(Exception ex)
{
System.Windows.MessageBox.Show($"Overriding ShouldRetryOn.");

bool retry = false;

SqlException sqlException = GetSqlException(ex);

if (sqlException != null)
{
int[] errorsToRetry =
{
1205, //Deadlock
-2 //Timeout
};

if (sqlException.Errors.Cast<SqlError>().Any(x => errorsToRetry.Contains(x.Number)))
{
retry = true;
}
}

if (ex is TimeoutException)
{
retry = true;
}

return retry;
}
}

在这段特定的代码中,我根本没有遇到任何问题。

可能值得注意的一件事是,到目前为止我看到的每个示例(例如 http://blog.analystcircle.com/2015/08/01/connection-resiliency-in-entity-framework-6-0-and-above/ )都使用
SqlException sqlException = ex as SqlException;

我发现使用这种方法总是会导致一个空的 SqlException,因为我的程序抛出了一个无法转换为 SqlException 的 EntityException。我的底层SqlException其实就是EntityException内部异常的内部异常。所以,我整理了一个简短的递归调用来深入挖掘并找到它。
private SqlException GetSqlException(Exception ex)
{
SqlException result = ex as SqlException;

if (result == null && ex.InnerException != null)
result = GetSqlException(ex.InnerException);

return result;
}

这工作正常,但是当我发现的示例没有时我需要这样做的事实可能是关于出了什么问题的线索。 EntityExceptions 不会触发 DbExecutionStrategy 吗?如果不是,为什么将其列为与 EF 6 一起使用的解决方案?任何见解将不胜感激。

编辑:
进一步挖掘 DbExecutionStrategy ( https://github.com/aspnet/EntityFramework6/blob/master/src/EntityFramework/Infrastructure/DbExecutionStrategy.cs ) 的源代码后,我发现从 EntityException 中查找 SqlException 的递归函数是不必要的。 DbExecutionStrategy 有一个 UnwrapAndHandleException 函数,它就是这样做的,并将 SqlException 传递给 ShouldRetryOn。所以,看来我又回到了第一站。

编辑 2:
不是真正的解决方案,因为它没有解释为什么我的 DbExecutionStrategy 没有被调用,但我发现如果我显式调用执行策略,它就可以工作。

显式使用执行策略的代码是:
var executionStrategy = new MyConfiguration.MyExecutionStrategy();

executionStrategy.Execute(
() =>
{
//build your context and execute db functions here
using (var context = new Entities())
{
...do stuff
}
});

最佳答案

现在可能太老了,但以防万一有人遇到同样的问题:

  • exception.GetBaseException() 为您提供任何异常的根本原因。不需要递归
  • 我可以使用 EF 6.4.0
  • 使其工作

    关于c# - 我的自定义 DbExecutionStrategy 没有被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49752988/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com