Besides translating Relational data to Object model, The ORM has other roles, as:
- Lazy Loading
- Automatic change detection
- Transactions
However, with Repository pattern translating ORM's DTOs to Domain Models, that happens:
- Can't use the benefits of Lazy Load, since I need to fill my entire Domain Model and Repository doesn't know what data Domain needs.
- ORM can't detect changes, since Domain Model isn't from ORM world.
- Can't do many transactions at once, again, due the lack of Domain knowledge about ORM
Question 1: Am I missing some gap where I can have the full benefits of Lazy Loading, Transactions and Automatic change detection in a domain-driven-design scenario? Or these benefits are more for another approach (such as Active Record) than DDD?
Question 2: Why orm is so mentioned in DDD books? Just for the relational to domain model and Lazy Loading, Transactions and Change Detection is fully discarted
Some platforms has code-first approach, which is a way to improve these problems, however this feature is not always present in many environments or simply is not able to use (in a legacy database for eg.), so it's not a solution.
The Repository pattern implements separation of concerns by abstracting the data persistence logic in your applications. Design patterns are used as a solution to recurring problems in your applications, and the Repository pattern is one of the most widely used design patterns.
The ORM is an implementation detail of the Repository. The ORM just makes it easy to access the db tables in an OOP friendly way. That's it. The repository abstract persistence access, whatever storage it is.
No, the repository/unit-of-work pattern (shortened to Rep/UoW) isn't useful with EF Core. EF Core already implements a Rep/UoW pattern, so layering another Rep/UoW pattern on top of EF Core isn't helpful.
The Repository Pattern allows us to create an abstraction layer between the data access layer and the business logic layer of an application. So, this Data Access Pattern offers a more loosely coupled approach to data access.
I have been thinking for some time that if one were to remove the change-tracking from an ORM then developers would see far less value in them.
Lazy-loading should never happen. An aggregate is always loaded in its entirety. If you find yourself requiring lazy-loading chances are that you are querying your domain model. This is something you should not do. Use a simple query layer / read model for that.
Transactions really are a DB concern and would not impact DDD directly. Aggregates do represent a consistency boundary so a database transaction is a natural fit but that is where it ends.
You could still use an ORM tool with DDD but you probably will get less mileage. I do not like ORMs at all and if I have any choice in the matter I simply do not use them. The mapping is really not all that much work and if done in a custom mapper class runs at language speeds as opposed to some proxy mechanism.
There are instances that I have seen where domain objects are, for instance, persisted directly using an ORM. However, if I have to mark anything using, say, an attribute or even change my design where I have to implement certain methods as virtual
or even structure certain classes in a specific way I no longer regard my domain as persistent ignorant, and that is something I really want (PI).
However, with Repository pattern translating ORM's DTOs to Domain Models, that happens:
- Can't use the benefits of Lazy Load, since I need to fill my entire Domain Model and Repository doesn't know what data Domain needs.
- ORM can't detect changes, since Domain Model isn't from ORM world.
- Can't do many transactions at once, again, due the lack of Domain knowledge about ORM
There is no need to implement another layer for mapping ORM's entities into Domain Entities when modern ORMs are used. In the .NET world either Entity Framework or NHiberate are able to map your Rich Domain Model into Relational Data Base.
Code-First approach can be used with both of them.
First Domain Model is designed, then Data Base is generated using mappings (Entity Framework Fluent Api / Fluent NHibernate Mappings) or conventions (EF Custom Code First Conventions / Fluent NHibernate Auto Mapping)
There are some related SO questions:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With