I've configured my db context to retry on failure this way:
optionsBuilder.UseSqlServer(connectionString, sqlServerOptionsAction: sqlOptions => {
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 10,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null);
});
Also I have configured following interceptor:
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;
}
}
}
So basically I'm expecting when fetching entities from the database to hit Throw method 3 times, 2 with throwing exception and last time without throwing it. But actually there is no retry on failure and after first exception execution is getting stopped. What am I doing wrong?
I have such helper for resilient transactions:
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);
}
And here is the way I am executing it:
await ResilientTransaction.New(_dbContext).ExecuteAsync(async () => {
_dbContext.Tenants.Add(new Tenant());
await _dbContext.SaveChangesAsync();
});