LyraLearn AI Learning Platform
Exams
← Module 4 Β· EF Core and Data Scenarios
🎧 Listen

Transactions and Concurrency

The setup is always a story: "Two case workers open the same candidate record. Both edit it. Both hit Save. What happens in your app today β€” and what should happen?" This scenario is a gift, because the honest first answer is unglamorous: last write wins, silently. Saying that plainly earns trust; pretending your CRUD app already handles it does not.

The two-users answer, structured

Clarify first: "Does the business actually care? For a notes field, last-write-wins may be fine. For a certification decision on a transcript, it isn't." Then present the standard fix: optimistic concurrency. Add a rowversion column, map it as a concurrency token ([Timestamp] or IsRowVersion() in Fluent API), and EF appends WHERE RowVersion = @original to every UPDATE. If zero rows match, EF throws DbUpdateConcurrencyException β€” the record changed under you.

The part most candidates skip, and interviewers notice: what the user sees next. Catching the exception is not a strategy. Say what you'd do with it β€” reload the current values, show "this record was changed by someone else," and let the user merge or retry. In an MVC app that means round-tripping the row version in a hidden field on the edit form. Contrast briefly with pessimistic locking (holding a lock or a "checked out by" flag) and explain why optimistic wins for web apps: no abandoned locks when someone closes a browser tab.

Transactions: when SaveChanges isn't enough

Know the baseline cold: one SaveChanges() call is already atomic β€” EF wraps it in a transaction. You need an explicit transaction (Database.BeginTransactionAsync) when a unit of work spans multiple SaveChanges calls or mixes EF with raw SQL/Dapper. The advanced probe: "You've enabled connection retries β€” why did your transaction code start throwing?" Answer: EnableRetryOnFailure requires retriable units, so you wrap the whole transaction in CreateExecutionStrategy().ExecuteAsync(...) β€” the strategy can replay the entire block.

That leads into idempotent retries: if a retry replays your block, it must be safe to run twice. Check-then-insert patterns need unique constraints as the backstop; money-moving or status-advancing operations need an idempotency key or a state check inside the transaction.

Answers that fall flat

Practice prompts

🧠 Quiz yourself on this lesson →

Ask the AI Tutor

Grounded in the course lessons β€” it cites its sources and says when it doesn't know.