A database transaction groups database operations into a single unit whose changes are either kept together or rolled back. This atomicity prevents a business operation from leaving related data inconsistent. section 10.2
Separate connections can create separate transactions for each database call. That is acceptable for read-only work, but dangerous when one operation mutates related records: saving a company and then failing to save its users can produce inconsistent data. Separate the decisions about what to update and whether to keep those updates, then let one transaction govern the business operation. section 10.2
Making ChangeEmail atomic
A fragile controller reads a user and company, changes the email, saves the company, saves the user, and dispatches an event. If each repository opens its own connection, the two saves are not one atomic operation. Inject a shared transaction into the repositories so both updates participate in the same unit. A unit of work can improve this arrangement by deferring all updates until the business operation ends, shortening the transaction’s lifetime and reducing data congestion.
Apply these transaction rules when testing database integration:
- Use the same database management system in tests and production rather than relying on an in-memory database. section 10.7
- Do not reuse transactions or units of work between arrange, act, and assert sections; each section should have its own. section 10.7
- Prefer clearing leftover data at the start of a test over an overarching never-committed transaction, which can behave differently from production. section 10.3













