Start here. This is the direct spoken answer to practice first.
Why this question matters
A transaction boundary is a business correctness decision expressed through the database. It covers only the changes that must commit or roll back together, and its duration determines how long locks and other resources remain occupied.
I put database changes in one transaction when partial success would violate an invariant. Creating an order header, its lines, and the inventory reservation may need one atomic unit, while unrelated logging does not. EF Core already wraps one SaveChanges call in a transaction when needed; I use an explicit transaction when several saves or queries and writes must share the same boundary. I keep it short and do not wait on external HTTP calls inside it.