Page 12 - MSDN Magazine, October 2017
P. 12
Data Points JULIE LERMAN DDD-Friendlier EF Core 2.0, Part 2
In my September column (msdn.com/magazine/mt842503), I laid out the many Entity Framework Core (EF Core) 2.0 features that align nicely with Domain-Driven Design (DDD) principles. In addition to providing great guidance and patterns for software development, DDD principles are also critical if you’re designing microservices. In the examples throughout the article, I used simplistic patterns in order to focus on the particular EF Core feature. Doing this meant that the code didn’t represent well-designed DDD-guided classes, andIpromisedthatinanupcomingcolumnI’devolvethoseclasses to look more like what you might write for a real-world implemen- tation using DDD. And that’s what I’m going to do in this article. I’ll walk you through these better-architected classes and show you how they continue to work well as I use EF Core 2.0 to map them to my database.
The Original Domain Model
I’ll begin with a quick refresher on my little domain model. Because it’s for a sample, the domain lacks the complex business problems that would generally drive you to lean on DDD, but even without those complicated problems, I can still apply the
this data. I evolved the Entrance property to be tied to a backing field, and then modified the mappings to let EF Core know about this, as well.
PersonName_ValueObject (named so elaborately for your ben- efit) is a value object type without its own identity. It can be used as a property in other types. Samurai has a PersonName_Value- Object property called SecretIdentity. I used the new EF Core Owned Entity feature to make SamuraiContext know to treat the SecretIdentity the same as earlier versions of EF would handle a ComplexType, storing the properties of the value object in columns of the same table to which the Samurai type maps.
The Enhanced Domain Model
What follows are the more advanced classes in the aggregate, along with the EF Core 2.0 DbContext I’m using to map to the database, which in my case happens to be SQLite. The diagram in Figure 1 shows the aggregate with its class details. The code list- ings will start with the non-root entities and finish up with the root, Samurai, which controls the others. Note that I’ve removed
* 1
patterns so you can see them in action, and see how EF Core 2.0 responds to them.
The domain comprises the Samurai characters from the movie “Seven Samurai,” where I keep track of their first appearance in the movie and their secret identities.
In the original article, the Samurai was the root of the aggregate and I had con- strained the model to ensure the Samurai was responsible for managing its entrances and its secret identity. I demonstrated some of those constraints as follows:
Samurai and Entrance have a one-to- one relationship. Samurai’s Entrance field is private. Entrance has a foreign key field, SamuraiId. Because Samurai.Entrance is private, I needed to add a Fluent API mapping in the DbContext class to be sure EF Core was able to comprehend the relationship for retrieving and persisting
11
Quote (Child Entity)
Attributes
Id
Text
SamuraiId SamuraiGuidId
Methods
Quote() ctor Quote(Guid, ...) ctor
Samurai (Aggregate Root)
Attributes
Id SamuraiGuidId Name
IsDirty
Quotes Entrance EntranceScene SecretIdentity
Methods
Samurai() ctor Samurai(string) ctor AddQuote(string) CreateEntrance(int, ...) RevealSecretIdentity() Identify(string, string)
PersonFullName
(Value Object)
Attributes
First Last
Methods
PersonFullName() ctor Create(string, string) Empty()
IsEmpty()
FullName()
Entrance (Child Entity)
Attributes
Id
MovieMinute SceneName ActionDescription SamuraiFk SamuraiGuidId
Methods
Entrance() ctor Entrance(Guid, ...) ctor
Code download available at msdn.com/magazine/1017magcode.
8 msdn magazine
1
Figure 1 Diagram of the Advanced Aggregate
1