While it is possible to use composition to inject every relevant repository into a unit of work, this becomes quite unwieldy and clumsy for any non-trivial amount of repositories, on top of being an OCP violation.
In .Net Core, I've found a nicer way to approach this. In short, it relies on the DI container to connect the db context to both the repositories and the unit of work, without requiring you to directly connect the repositories and the unit of work.
This works neatly out of the box for any web-based context as you can rely on the DI scope to treat your dependencies as a singleton only within a single web request. A similar thing can be done for non-web contexts but it requires more configuration, and a unit of work factory may be simpler in that case.
This can be achieved by doing the following:
- Register the db context into the DI container as a scoped entry.
- Inject the db context in the unit of work constructor.
- The unit of work only interacts with the committing of the db context.
- Register the unit of work into the DI container. It doesn't matter if it's scoped or transient as the context itself will already be scoped.
- Inject the db context in the repository constructor.
- The repository only interacts with the sets of the db context, it does not commit any changes.
- Register the repository into the DI container. It doesn't matter if it's scoped or transient as the context itself will already be scoped.
This enables your consumer to request the appropriate dependency based on what it needs to do:
- If your consumer wants to get/set data, inject whatever repository is relevant for the job at hand.
- If your consumer wants to commit any made changes, inject the unit of work.
Generally speaking, my domain logic only interacts with repositories, whereas my business service is the only one using the unit of work to commit any changes that have been made to the db context (indirectly via the domain logic).
I find this a much cleaner approach that avoids the clumsy manual composition of all repositories into the unit of work.