You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
*[](https://github.com/mkenney/software-guides/blob/master/STABILITY-BADGES.md#beta)**SQLAlchemy manager:** Implementation is mostly finalised, needs testing in production.
33
-
*[](https://github.com/mkenney/software-guides/blob/master/STABILITY-BADGES.md#work-in-progress)**Repository / Unit of work:**Major work is stil necessary to finalise the interface, to hide the session management implementation details from the application.
33
+
*[](https://github.com/mkenney/software-guides/blob/master/STABILITY-BADGES.md#beta)**Repository / Unit of work:**Implementation is mostly finalised, needs testing in production.
34
34
35
35
36
36
## SQLAlchemy manager
@@ -212,10 +212,10 @@ A `Repository` represents a generic interface to persist data object to a storag
212
212
using SQLAlchemy. It makes sense that the lifecycle of a `Session` follows the one of the Repository
213
213
(If we create a Repository, we're going to do a DB operation, otherwise we don't need a `Session`)
214
214
215
-
This ensures we the `Session` we use is isolated, and the same for all the operations we do with the
216
-
repository.
215
+
This ensures the `Session` we use is isolated, and the same for all the operations we do with the
216
+
same repository.
217
217
218
-
The consequence of this choice is we can't use SQLAlchemy lazy loading, so we need to make sure
218
+
The consequence of these choices is we can't use SQLAlchemy lazy loading, so we need to make sure
219
219
relationship are loaded eagerly. You can do this by:
220
220
221
221
* Setup your model/table relationships to always use always eager loading
@@ -224,35 +224,35 @@ relationship are loaded eagerly. You can do this by:
224
224
Also `AsyncSession` has [the same limitation on lazy loading](https://docs.sqlalchemy.org/en/20/orm/extensions/asyncio.html#asyncio-orm-avoid-lazyloads)
225
225
so it makes sense that the two repository implementations behave consistently.
226
226
227
-
### Use the Unit Of Work to share a session among multiple repositories[alpha]
227
+
### Use the Unit Of Work to share a session among multiple repositories
228
228
229
229
It is possible we need to run several operations in a single database get_session. While a single
230
230
repository provide by itself an isolated session for single operations, we have to use a different
231
231
approach for multiple operations.
232
232
233
-
We can use the `SessionHandler` or the `SessionHandler` class to provide a shared session to
233
+
We can use the `UnitOfWork` or the `AsyncUnitOfWork` class to provide a shared session to
234
234
be used for repository operations, **assumed the same bind is used for all the repositories**.
235
235
(Two phase transactions are not currently supported).
236
236
237
-
All repositories operation methods accept the `session` parameter for this purpose. This makes the
238
-
operations to bypass the internal repository-managed session.
239
-
240
237
```python
238
+
classMyRepo(SQLAlchemyRepository):
239
+
_model = MyModel
240
+
classMyOtherRepo(SQLAlchemyRepository):
241
+
_model = MyOtherModel
242
+
241
243
bind = sa_manager.get_bind()
242
-
repo1 = MyRepo(bind)
243
-
repo2 = MyOtherRepo(bind)
244
-
uow = SessionHandler(bind)
244
+
uow = UnitOfWork(bind, (MyRepo, MyOtherRepo))
245
245
246
-
with uow.get_session() as _session:
247
-
repo1.save(some_model, session=_session)
248
-
repo2.save(some_model, session=_session)
246
+
with uow.transaction():
247
+
uow.MyRepo.save(some_model)
248
+
uow.MyOtherRepo.save(some_other_model)
249
249
250
250
# Optionally disable the commit/rollback handling
251
-
with uow.get_session(commit=False) as _session:
252
-
model1 =repo1.get(1, session=_session)
253
-
model2 =repo1.get(1, session=_session)
251
+
with uow.transaction(read_only=True):
252
+
model1 =uow.MyRepo.get(1)
253
+
model2 =uow.MyOtherRepo.get(2)
254
254
```
255
255
256
256
Both the UnitOfWork classes create an internal `scoped_session` or `async_scoped_session`, behaving
257
257
in the same way at the repositories do. This provides the freedom to tune the session lifecycle based
258
-
on our application requirements (e.g. one session per http request, per domain, etc.)
258
+
on our application requirements (e.g. one unit of work per http request, per domain, etc.)
0 commit comments