The best way to create DTOs from entities and update entities from DTOs in a layered architecture

design-patternsdomain-driven-designdtoenterprise-architecture

Option 1:

At first I would make a call to my service layer, which served as an API for my core domain, to get a domain object or a list of domain objects and then pass them into the assembler which would construct the DTOs I needed for my view. The problem I have with this approach are cases where the domain object is large and I don't want to load in the whole object just to copy a few fields needed for the DTO (ie showing a list of summaries entities).

Option 2:

The next approach I used was to wire in a repository (for read-only purposes) into my assembler so that I could only query the database for the fields I need in the DTO. I can also use this repository when I get a DTO and need to use it to update and entity. For example, a DTO filled will values I need to update on my entity comes into my assembler, the assembler looks up the entity from a repository and then overlays the information from the DTO on the entity and then returns the entity. The controller then calls the service layer to save the entity that the assembler returned.

Option 3:

I could wire in the repositories directly into the controllers but something about exposing the repository in the controller seems wrong to me because the service layer should be handling transactions and security, but then again, if I put a repository in the assembler I am basically doing the same thing.

Any thoughts are welcome. I just want to understand pros and cons and what has worked well for others.

Best Answer

Ok. Problem 1: getting DTO's from entities:

Since your entities can expose their data publicly you can access their properties and instantiate DTO object or simply serialise the entity directly

Problem 2 : Entities from DTO's:

A constructor method which takes a list of the properties to be set can be called using the properties of the DTO

Problem 3 : large entities when you only need summary info

Create a new summary object which you can retrieve from the repository. Note I suggest you make strongly typed repositories with methods like Repo.GetMyObjectById(string id) rather than expose a generic ORM.

Problem 4 : where to orchestrate all this.

My recommendation is to have a service class one level below your hosting service/app/website.

This has access to the repositories DTO's and entities and its methods map to the controllers/service calls of your application so that you do not need any code at the top level and can host the same service in multiple ways.

Giving it access to the repos is not an issue when you can only use them to retireve entities rather than doing any query they like.

Putting this assembly/orchestration logic inside the entity is usually bad as you will want the entity to be reused for other purposes.

This top level service should be very light. Just, get these objects, call this method, create and return the result/DTO/viewmodel

Because its so light its not a massive prob if you skip the layer and put the code in your controller. But it will save you time if you change the hosting layer and help with testing etc