我已经配置了我的数据库上下文以在失败时进行重试,如下所示:
基本上,我期望从数据库中获取实体时会调用Throw方法3次,前两次会抛出异常,最后一次则不会抛出。 但事实上,在第一次发生异常后,执行将停止,没有重试失败的操作。 我做错了什么?
我有一个用于弹性事务的帮助程序:
optionsBuilder.UseSqlServer(connectionString, sqlServerOptionsAction: sqlOptions => {
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 10,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null);
});
我还配置了以下拦截器:
public class DbCommandFailureInterceptor : DbCommandInterceptor
{
private int retryCount = 2;
public override async Task<InterceptionResult<int>> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)
{
Throw(command);
return result;
}
public override async Task<InterceptionResult<DbDataReader>> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result, CancellationToken cancellationToken = default)
{
Throw(command);
return result;
}
private void Throw(DbCommand command)
{
if (!(command.CommandText.Contains("serverproperty")
|| command.CommandText.Contains("_MigrationHistory"))
&& retryCount > 0) {
--retryCount;
throw SqlExceptionFaker.Error10053;
}
}
}
基本上,我期望从数据库中获取实体时会调用Throw方法3次,前两次会抛出异常,最后一次则不会抛出。 但事实上,在第一次发生异常后,执行将停止,没有重试失败的操作。 我做错了什么?
我有一个用于弹性事务的帮助程序:
public class ResilientTransaction
{
private readonly DbContext _context;
private ResilientTransaction(DbContext context) =>
_context = context ?? throw new ArgumentNullException(nameof(context));
public async Task ExecuteAsync(Func<Task> action)
{
var strategy = _context.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () => {
using (var transaction = await _context.Database.BeginTransactionAsync()) {
await action();
await transaction.CommitAsync();
}
});
}
public static ResilientTransaction New(DbContext context) =>
new ResilientTransaction(context);
}
以下是我执行它的方法:
await ResilientTransaction.New(_dbContext).ExecuteAsync(async () => {
_dbContext.Tenants.Add(new Tenant());
await _dbContext.SaveChangesAsync();
});