Search code examples
domain-driven-design

Mapping tables to domain classes in a DDD architecture


My application is broken down into several assemblies.

The MyProject.Core assembly contains all of the Domain objects such as Person and Sale as well as interfaces repositories such as IPersonRepository and ISaleRepository.

The MyProject.Data is supposed to deal with persistence, but I'm a little confused about how this is supposed to work. Am I supposed to be using Entity Framework to map my tables to the domain models? Should I do this with the Fluent API? Or am I supposed to be instantiating the model classes and populating them manually?


Solution

  • IMO you should not try to use your domain model objects as entity framework entities. You will not be able to craft properly encapsulated domain objects consisting of atomic methods. Instead they would need to have public properties with getters and setters that EF require, and this leads to an Anemic Domain Model.

    Essentially: if you try to double up your domain objects as entity framework entities, you will compromise the design.

    Instead, I employ something that loosely resembles the memento pattern, whereby I re-hydrate my domain objects with EF entities that serve as the "mementos". Vaugh Vernon calls these objects "state objects"

    Given that EF can just use plain POCO's I'd put these classes in a different assembly to the assembly hosting your DbContext/Respositories, as your model will need to reference them. Because they are just POCO's you won't be tying your model to EF.

    So you'd potentially have three assemblies:

    • MyProject.Model / MyProject.Core / MyProject.Domain ... which contains your DDD model classes & repository interfaces
    • MyProject.Infrastructure ... which contains DBContext, Repository Implementations & State objects

    Example:

    public class PersonRepository  : EntityFrameworkRepository, IPersonRepository
    {
          public Person GetById(Guid personId)
          {
               using (MyDbContext ctx = new MyDbContext())
               { 
                   var personState = (from p in ctx.People
                                       where p.PersonId == personId
                                       select p).FirstOrDefault(); 
    
    
                   return Person.RestoreFromState(personState );
    
               }
          }
    }
    

    UPDATE

    With EF Core you can now map to private fields so you might not need to add this level of complexity to keep the integrity of your design.

    Also, I'd recommend the following post from Vaughn Vernon on the subject: https://kalele.io/modeling-aggregates-with-ddd-and-entity-framework/