Complete worked example
python
from sqlalchemy import create_engine, select, text
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Role(Base):
__tablename__ = "roles"
id: Mapped[int] = mapped_column(primary_key=True)
score: Mapped[int]
def inspect_example(score):
engine = create_engine("sqlite+pysqlite://", connect_args={"autocommit": False})
try:
Base.metadata.create_all(engine)
with Session(engine) as session:
role = Role(score=score)
session.add(role)
during = session.scalar(text("SELECT count(*) FROM roles"))
assigned = role.id is not None
session.rollback()
with Session(engine) as check:
after = check.scalar(text("SELECT count(*) FROM roles"))
return {"during": during, "assigned": assigned, "after": after}
finally:
engine.dispose()- Reasoning
- The example adds a Role, then executes a textual SELECT count(*) through the same Session. Under the pinned 2.1 configuration, execution flushes the pending insert: during becomes one and assigned is True. The program then rolls back rather than committing. A new Session observes after equal to zero. These three facts belong together: the database saw a row inside the first transaction, the object acquired an ID, and no row survived the rollback. Returning a generated ID alone would not prove that an insert became durable or visible to a later unit of work.