4

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?

NoPyGod
  • 4,905
  • 3
  • 44
  • 72
  • *"I'm a little confused about how this is supposed to work. Am I supposed to be using Entity Framework"*. DDD does not prescribe *how* things are "supposed" to work at this level. All 3 of the approaches you identified are valid. I suspect you are asking which of those approaches is the *best*. The only real answer to that is *"it depends"*. – MattDavey Jun 14 '13 at 14:10

3 Answers3

3

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/

David Masters
  • 8,069
  • 2
  • 44
  • 75
  • It's not true that EF needs public properties. It's true only in a case of fluent mapping. When you use edmx file instead then you can map also private properties. – Bartłomiej Szypelow Jun 10 '13 at 11:29
  • Thanks I didn't know that. Probably because I only use the 'Code First' approach and never use an edmx. – David Masters Jun 14 '13 at 14:25
  • 1
    The level of complexity in the solution you're advocating is a little scary. In the end I decided to use the EF Fluent API to map my database to my domain models and so far it seems to work really really well. At any point if I decide one particular mapping is too complicated I can just refactor the one repository. I'll tick your answer though because it's food for thought, thanks! – NoPyGod Jun 17 '13 at 05:02
  • 3
    I agree it adds to the complexity, but it's a trade-off. I don't want public ICollection properties exposed on my domain objects allowing them to be added to the collection without validation; I prefer **myAggregateRoot.AddSomeEntity(someEntity)**, which adds to a private collection. So far I haven't seen a way of getting EF code-first to map directly to the private collection without removing the 'POCO' nature of my objects. – David Masters Jun 17 '13 at 10:44
  • 2
    I'm late to the party but I don't see how this is memento design pattern. Any client can mingle with internals of memento, while in the book it's explicitly stated that only Originator could use such wide interface. Basically you're just masquerading it under the fancy design pattern. – Milivoj Milani Nov 20 '14 at 09:57
  • What about GORM in golang? What should be the approach? should we return GORM models to service layer? – Ashutosh Singh Oct 07 '21 at 20:36
  • @MilivojMilani I take your point - it isn't strictly speaking the memento pattern as per the book. I've updated the answer to reflect this. – David Masters Feb 09 '22 at 09:36
1

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?

Use what you know, or if allowed, what you want to learn.

Either way you should not leak any DB specific information back to the domain model or put any DB restrictions on the model.

jgauffin
  • 99,844
  • 45
  • 235
  • 372
0

The industry standard practice is to use some sort of Object/Relation Mapper such as Entity Framework or NHibernate etc to load and persist you entities.

O/RMs are tools for bridging the Impedance Mismatch between Object Oriented laguages and Relation Databases.

They are often combined with the Repository Pattern.

It is not essential to use these tool, you could manually save your entities to a database, or possibly build you own O/RM, but will will be creating yourself many unnecessary headaches. By using an O/RM tool, you will be gaining the benefit of many others experience in building DDD applications.

It is also worth poiting out that O/RM's are not only for DDD applications.

In my applications, the Data layer is usually a few repositories, the NHibernate mapping files and any other NHibernate implementation code.

Paul T Davies
  • 2,527
  • 2
  • 22
  • 39