Rich domain model with behaviours and ORM
.net, architecture, c#, domain-driven-design, orm
Solution
This is actually a very good question and something I have contemplated. It is potentially difficult to create proper domain objects that are fully encapsulated (i.e. no property setters) and use an ORM to build the domain objects directly.
In my experience there are 3 ways of solving this issue:
- As already mention by Luka, NHibernate supports mapping to private fields, rather than property setters.
- If using EF (which I don't think supports the above) you could use the memento pattern to restore state to your domain objects. e.g. you use entity framework to populate 'memento' objects which your domain entities accept to set their private fields.
- As you have pointed out, using CQRS with event sourcing eliminates this problem. This is my preferred method of crafting perfectly encapsulated domain objects, that also have all the added benefits of event sourcing.
Problem
After watching NDC12 presentation "Crafting Wicked Domain Models" from Jimmy Bogard (http://ndcoslo.oktaset.com/Agenda), I was wandering how to persist that kind of domain model. This is sample class from presentation: ``` public class Member { List<Offer> _offers; public Member(string firstName, string lastName) { FirstName = firstName; LastName = lastName; _offers = new List<Offer>(); } public string FirstName { get; set; } public string LastName { get; set; } public IEnumerable<Offer> AssignedOffers { get { return _offers; } } public int NumberOfOffers { get; private set; } public Offer AssignOffer(OfferType offerType, IOfferValueCalc valueCalc) { var value = valueCalc.CalculateValue(this, offerType); var expiration = offerType.CalculateExpiration(); var offer = new Offer(this, offerType, expiration, value); _offers.Add(offer); NumberOfOffers++; return offer; } } ``` so there are some rules contained in this domain model: - Member must have first and last name - Number of offers can't be changed outside - Member is responsible for creating new offer, calculating its value and assignment If if try to map this to some ORM like Entity Framework or NHibernate, it will not work. So, what's best approach for mapping this kind of model to database with ORM? For example, how do I load AssignedOffers from DB if there's no setter? Only thing that does make sense for me is using command/query architecture: queries are always done with DTO as result, not domain entities, and commands are done on domain models. Also, event sourcing is perfect fit for behaviours on domain model. But this kind of CQS architecture isn't maybe suitable for every project, specially brownfield. Or not? I'm aware of similar questions here, but couldn't find concrete example and solution.