Commit is the point at which a database transaction finalizes its changes. For a money transfer, crediting one account and debiting another must succeed together. Without a transaction, a failure after the credit can leave the accounts in an invalid state. section 11.2.1
Commit a transfer in EF Core
Start a transaction before either update. Credit and debit the accounts, then call `CommitAsync()` only after both operations succeed. If an operation fails, call `RollbackAsync()`, clear the EF Core change tracker, and rethrow the exception. Clearing the tracker prevents its in-memory account state from retaining changes the database rolled back. section 11.2.1
Listing 11.11 A transactional version of the BankRepository.TransferAsync
public async Task TransferAsync(
string from, string to, decimal amt)
{
using var tx = await
_ctxt.Database.BeginTransactionAsync(); #1
try
{
await CreditAsync(to, amt); #2
await DebitAsync(from, amt);
await tx.CommitAsync(); #3
}
catch #4
{
await tx.RollbackAsync(); #5
_ctxt.ChangeTracker.Clear(); #6
throw; #7
}
}
The transactional `TransferAsync` listing places `CommitAsync()` after both account updates and handles failure with rollback and change-tracker cleanup. section 11.2.1
A failure during commit is harder to handle than a failure before it: if the database connection drops, the application may not know whether the commit succeeded. Retrying blindly could repeat a successful transfer. EF Core’s default execution strategy does not handle this transaction pattern; a transaction-aware strategy can retry and, when possible, verify the outcome first. Account balances alone are not a reliable check because other transfers may change them between attempts. section 11.2.2 section 11.4




