Azure SQL Database临时故障处理失效,求助排查原因
核心原因
EF内部执行策略覆盖自定义重试逻辑
你在外层手动创建RetryPolicy,但Entity Framework的ExecuteSqlCommand方法内部会自动启动事务,并使用DefaultSqlExecutionStrategy——这个默认策略不会重试死锁(Deadlock)这类临时错误,导致你的自定义重试逻辑根本没机会触发。从错误栈能看到,异常最终从System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute抛出,说明EF用的是自身默认策略,而非你定义的SqlDatabaseTransientErrorDetectionStrategy。参数传递错误(潜在问题)
方法参数声明为object[] parameters,但调用ExecuteSqlCommand时用的是sqlParams,这会导致参数未正确传递,可能引发额外异常。临时错误检测策略匹配问题
即便你的重试逻辑生效,SqlDatabaseTransientErrorDetectionStrategy默认是否包含死锁错误?实际上死锁属于SQL Azure需重试的临时错误,但由于EF默认策略拦截了异常,你的策略根本没机会处理。
解决方案
1. 替换EF默认执行策略为SqlAzureExecutionStrategy
EF专为SQL Azure提供了SqlAzureExecutionStrategy,会自动重试包括死锁、连接超时、资源限制在内的所有临时错误,配置方式分EF Core和EF 6两种:
EF Core 配置示例
在DbContext中重写OnConfiguring方法:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer( "你的SQL Azure连接字符串", options => options.EnableRetryOnFailure( maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(1), errorNumbersToAdd: null)); }
EF 6 配置示例
创建自定义DbConfiguration类:
public class SqlAzureDbConfiguration : DbConfiguration { public SqlAzureDbConfiguration() { SetExecutionStrategy( "System.Data.SqlClient", () => new SqlAzureExecutionStrategy(10, TimeSpan.FromSeconds(1))); } }
在DbContext上标记使用该配置:
[DbConfigurationType(typeof(SqlAzureDbConfiguration))] public class YourDbContext : DbContext { // ... }
2. 移除外层自定义RetryPolicy
无需手动在外层套RetryPolicy,EF的SqlAzureExecutionStrategy会自动处理重试逻辑,避免和EF内部事务管理冲突。
3. 修复参数传递错误
将方法内的sqlParams改为parameters,确保参数正确传递:
public int ExecuteSqlCmd(string sql, object[] parameters) { return this.Database.ExecuteSqlCommand(sql, parameters); }
内容的提问来源于stack exchange,提问作者Sam

