Repository navigation
Entity Framework
using Carom;
using Carom.EntityFramework;
var written = await db.SaveChangesWithRetryAsync(retries: 3, cancellationToken);
var total = await db.ExecuteWithRetryAsync(() => db.Orders.SumAsync(o => o.Total), retries: 3, cancellationToken);The int overloads use a built-in check. A DbUpdateException is judged by its inner exception; with no inner exception it is not retried. An exception is retried when it is a TimeoutRejectedException, or when its message contains, ignoring case, one of: timeout, deadlock, connection, network, transport.
Carom has no provider dependency, so it does not read SqlException error numbers. The message check is a heuristic. If you need exact rules, use the Bounce overload with your own predicate.
DbUpdateConcurrencyException is not retried: a blind retry sends the same stale values and hits the same conflict.
var bounce = Bounce.Times(3)
.WithTimeout(TimeSpan.FromSeconds(5))
.When(ex => ex is DbUpdateException { InnerException: TimeoutException });
await db.SaveChangesWithRetryAsync(bounce, cancellationToken);This overload uses your Bounce as given. Without a When predicate it retries every exception except cancellation, the core default, not the transient check above. A Bounce timeout cancels the save itself (fixed in 2.0.1).
Retrying SaveChanges re-sends whatever the change tracker holds. That is safe for a transient connection failure before the commit, and not something Carom can check for you.
Written from the Carom source. The repository is the source of truth; if a page disagrees with the code, the code wins. Licensed MPL-2.0.
Core
Carom.Extensions
Integrations
Project