Does anyone have an idea if it is possible to implement the retry pattern with SaveChangesInterceptor
interceptor?
Here is the SavingChangesAsync
method.
public override async ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result,
CancellationToken cancellationToken = new CancellationToken())
{
int tryCount = 0;
while (tryCount < _maxRetries)
{
try
{
return await new ValueTask<InterceptionResult<int>>(result); //it doesn't cause an exception.
}
catch (DbUpdateConcurrencyException ex)
{
if (ex.Entries.All(e => e.Entity.GetType() != typeof(TEntity)))
{
throw;
}
Console.WriteLine(tryCount);
foreach (var entry in ex.Entries)
{
if (entry is TEntity)
{
await entry.ReloadAsync(cancellationToken);
}
}
await Task.Delay(_delay, cancellationToken);
}
catch (DbUpdateException ex)
{
Console.WriteLine("Testing");
}
tryCount += 1;
}
throw new DbUpdateConcurrencyException($"The maximum number of retries {_maxRetries} has been exceeded.");
}
also I implemented the SaveChangesFailedAsync
method.
public override async Task SaveChangesFailedAsync(DbContextErrorEventData eventData,
CancellationToken cancellationToken = new CancellationToken())
{
if (eventData.Exception is DbUpdateConcurrencyException myException)
{
await Task.Delay(_delay, cancellationToken);
foreach (var entry in myException.Entries)
{
await entry.ReloadAsync(cancellationToken);
}
try
{
await eventData.Context.SaveChangesAsync(cancellationToken);
InterceptionResult.Suppress();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
BTW, I know there is a usual way to handle that. inherit from DBContext and override savechanges, and I am using EF Core 5.0.