-
Notifications
You must be signed in to change notification settings - Fork 97
DDD entity patterns
This page explains how you can create Domain-Driven Design (DDD) styled EF Core entity classes. It also tells you the signature of that GenericServices looks for methods that it can use to create or update the entity and its aggregates.
If you are not clear about what DDD styled entity classes are, or you want a longer explanation then please read the article on my blog called Creating Domain-Driven Design entity classes with Entity Framework Core.
The idea is that any creation or update of an entity (and its aggregates) has to be done by methods
with a function-revealing name, e.g. AddReview. At the same time you must stop the ability to create/update
the data in any other way. This requires you to "lock-down" the entity class by:
- All properties should have a private setter.
- All collections should be of type IEnumerable<T>, so that nothing can be added/removed from the collection. The actual collection is handled by a backing field.
- The parameterless constructor should should be private (EF Core uses this for creating instance of read) Then creates should be done by either/both:
- A public constructors with all the parameters needed to create the entity correctly.
- A public static method with all the parameters needed to create the entity correctly. *The benefit of static methods is that they can return a status, so errors found during the construction can be fed back. The updates should be done by:
- Public methods with function-revealing names and parameters.
- The Order entity class.
- The Book entity class. Note: I have made one property.
PublishedOn, have a public setter so that I can compare the performance of an AutoMapper update and a DDD-Styled update.
When GenericServices calls a method to DDD-styled entity class it will have only loaded that entity class.
This means if your method needs some other part of the relationship then it must load itself.
You are allowed to have the DbContext as one of the parameters in your method call (either your actual
DbContext or the generic DbContext class).
You can standard constructors and update methods that return void, but if you want to return a IStatusGeneric, then you can. This allows you to return errors, or a success Message. The rules are:
- For update methods they can return
IStatusGeneric. This status result is combined into theCrudServices' status. - For static methods used to create an entity instance it must return the type
IStatusGeneric<TEntity>. Again, the status result is combined into theCrudServices' status, and the primary key(s) are copied back into the DTOs primary key(s) properties (in case you need them).
You can find more about the pattern I use by looked in at the Summarising the DDD-style in my article and studying the entity classes in the DataLayer/EfClasses directory.
Note that some of the entities are Read-Only, i.e. they can only be created/updated via the root entity class.