Files
MetaORM/docs/guide/container.md
2026-08-17 14:22:34 +03:00

54 lines
1.8 KiB
Markdown

# Multi-Repo Transactions
Use `RepositoriesContainer` when you need a single atomic transaction spanning multiple repositories.
## Creating a container
```python
from metaorm import RepositoriesContainer, RepositorySettings
settings = RepositorySettings(dsn="sqlite+aiosqlite:///:memory:")
container = RepositoriesContainer(settings=settings)
```
## Getting repositories
```python
user_repo = container.get_repository(UserRepository)
order_repo = container.get_repository(OrderRepository)
```
## Atomic transaction across repositories
```python
async with container.transaction():
user = await user_repo.create_item(UserTable(name="Alice"))
await order_repo.create_item(OrderTable(user_id=user.id, total=100))
```
`container.transaction()` stores the session in a `contextvars.ContextVar`. All repository operations within the `async with` block automatically reuse that session. Nested `transaction()` calls yield the same session.
## Creating tables via container
You can also create tables for multiple repositories at once:
```python
await container.create_tables(UserRepository, OrderRepository)
```
## Nested transactions (savepoints)
For partial rollback inside a shared transaction use `container.nested_transaction()` (or `repository.nested_transaction()`). It creates a SQLAlchemy savepoint: an error inside the block rolls back only the savepoint, leaving the outer transaction open for further operations or commit.
```python
async with container.transaction():
user = await user_repo.create_item(UserTable(name="Bob"))
try:
async with container.nested_transaction():
await order_repo.create_item(OrderTable(user_id=user.id, total=999.99))
raise ValueError("Rollback nested order")
except ValueError:
pass
# Bob stays, the order is rolled back
```