ef-core-transactions-and-concurrencylisted
Install: claude install-skill Sarmkadan/dotnet-senior-skills
# EF Core Transactions and Concurrency
## SaveChanges is already a transaction
One `SaveChanges` call commits all its changes atomically. The explicit-transaction review flags run in both directions:
```csharp
// WRONG: ceremony around what SaveChanges already guarantees
using var tx = await _db.Database.BeginTransactionAsync(ct);
_db.Orders.Add(order);
await _db.SaveChangesAsync(ct);
await tx.CommitAsync(ct);
// WRONG the other way: two commits, crash between them leaves the order without its outbox event
await _db.SaveChangesAsync(ct); // order
await _db.SaveChangesAsync(ct); // outbox message - separate transaction!
// RIGHT: one use case, one SaveChanges
_db.Orders.Add(order);
_db.OutboxMessages.Add(evt);
await _db.SaveChangesAsync(ct);
```
An explicit transaction is warranted for exactly: multiple `SaveChanges` calls that must commit together (e.g. getting a database-generated id mid-flow), raw SQL mixed with tracked changes, or a lock-holding read-then-write sequence. The application service owns the boundary - repositories calling `SaveChanges` internally turn one use case into N independent commits (see api-layer skill).
## The lost update, and why you already have one
Read-modify-write without a concurrency token means last-writer-wins: two users load the same row, both save, one edit silently vanishes. No exception, no log - discovered weeks later as "the system lost my changes".
```csharp
public class Order
{
[Timestamp] public byte[] RowVersio