Search code examples
domain-driven-designaggregaterootef-core-3.0

Modelling Aggregate Roots with EF Core 3.X


Lets say I have these entities:

  • Customer
  • Order
  • Product

All three are aggregate roots, because all three need to be loaded and modified independently of one another. Since aggregate roots cannot contain other aggregate roots, for the Order aggregate root, we need a couple of more entities: OrderCustomer and OrderProduct. These are read-only and children of the Order aggregate. This way, since Order aggregate needs the customer and product, it loads OrderCustomer and OrderProduct entities, which are read-only. Order never loads Customer or Product.

This all makes sense however, the question I have is, how is this implemented in EF Core where you cannot map multiple models to same table? Do you define the OrderCustomer and OrderProduct as non-mapped models and load them by hand in your Order repository? I dont see any other way to do this.

(Please dont suggest using stored procedures or direct SQL or anything like that)


Solution

  • The OrderProduct and OrderCustomer probably wouldn't be entities but rather value obejcts that have their data persisted along with the Order. Fetching the data from the existing Product and Customer tables would not be necessary and, in some cases, quite detrimental to your data integrity.

    Since one aggregate should not contain a reference to another aggregate the idea is, as you appear to have it, to reference the related aggregate by id. However, if you need more information than just the id you can, again along the lines that you seem to be thinking, create a value object that contains the id along with some pertinent bits. I like to have the value objects that are specific to the aggregate as nested classes to make it apparent where they belong but that is a design choice.

    As far as "duplicating* the data of the related aggregate in the Order to re-constitute the value object consider a Product that represents a pair of "red socks". If you only store the id and then later fetch the description using the product id the description may , in the meantime, have changed to "blue socks". That will result in some issues with your client. Denormalizing the product description into the Order (via an OrderLine or Order.Line) would not cause any confusion in that regard and keep the discrepancy internal to the company without affecting the customer since a pair of "red socks" had been ordered.