Coffe Cold
Coffe Cold

Reputation: 285

DDD : one aggregate root , multiple persistent datasources

In the Guide/eBook: .NET Microservices: Architecture for Containerized .NET Applications (related to the eShopOnContainers) in the chapter "Designing the infrastructure persistence layer" (page 213) is explained in general how an aggregate root can perform CUD operations against a persistent data source.

Two important starting points are mentioned :

  1. An aggregate is ignorant of methods of persistency and infrastructure following the Persistence Ignorance and the Infrastructure Ignorance principles (page 218). An aggregate is determined by the business and not by the infrastructure.
  2. One should only define one repository per aggregate root to maintain transactional consistency between the objects within the aggregate (page 213)

Unfortunately, in all further examples that are mentioned the aggregate root and all underlying objects that fall under it are within one and the same persistent data source.

The pattern then is as follows:

  1. A repository is created containing that aggregate
  2. In this repository a Unit of Work is injected during creation. This Unit of Work contains methods such as SaveChangesAsync, SaveEntitiesAsync, Update and so on.
  3. In a command, the Unit of Work manages the transactions to this one data source such as a database or similar.

I want to expand this pattern that the aggregate can write its data over 2 or more physical data sources depending on the underlying object type.

Starting from starting point 1, it is perfectly justified to have a root aggregate and its underlying object to be updated to different data sources depending on the type of underlying object. Examples mentioned are : a Database and an XML file, a database and a NOSQL 'database',a database and a service, a database and an IoT device. Because an aggregate must be ignorant to methods of persistence and infrastructure, to my opinion there is no need to argue about the design of the aggregate. I think nowhere in the book it is written that a aggregate root should persist within one data source.

At the same time, starting point 2 also seems perfectly justified. Because the complete set of objects within the aggregate root is edited, and the successful persistence of the entire package is coordinated from one repository and (preferably) from one Unit of Work.

The question is: How deals Domain Driven Design if within the aggregate - depending on the type of the underlying object - it is hydrated over different data sources? Should I use one custom Unit of Work and make the decision where to write to within this UoW ?

I'm aware of the next question , but having studied the code I think it only deals with inheritance of repositories that deal with different data sources, but still serving one data source at the time and that is not what I'm after.

Upvotes: 2

Views: 1865

Answers (1)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57299

I want to expand this pattern that the aggregate can write its data over 2 or more physical data sources depending on the underlying object type.

Why do you want to do that on purpose?

In most cases, the persistence implementation is chosen to serve the domain, rather than the other way around. So the happy path typically involves choosing a persistence solution that can record the state of the entire aggregate, and storing the entire thing within a single transaction.

So if you find yourself trying to store an aggregate in two different places, you should take a hard careful look at why.

One common answer is that you want to be able to query the aggregate state efficiently. is a common solution here - rather than persisting the aggregate in two different data stores, you persist it to one and replicate it to another. The queries can run very efficiently against the replica (although there is of course some additional latency between a change to the aggregate and the reflection of that change in the query results).

Another common answer is that you really have two aggregates that reference each other. Nothing wrong with storing two aggregates in different places. You may be better served by making the distinction between the two explicit in your code.

How deals Domain Driven Design if within the aggregate - depending on the type of the underlying object - it is hydrated over different data sources?

Badly, just like everybody else.

Upvotes: 2

Related Questions