I have a web application being built using DDD and Onion architecture in .NET Core 5.
There are 4 layers:
Reference to infrastructure layer via API layer is only to connect to the database and any request to database will go via application layer; the application layer has interfaces that are implemented in the infrastructure layer to save and retrieve data from the database.
Now, when I create database using a code-first or database-first approach, where should these EF model classes should go?
Placing them in the domain layer will break the onion architecture, as the domain layer should not know anything about the infrastructure layer.
I have seen couple of examples where models and mappings are placed in domain model and those mappings are used in infrastructure layer OnModelCreating(..)
, but still the infrastructure layer mappings which are database-specific are present in the domain layer. What if I want to replace the infrastructure layer with some other database, in which case I need to change the domain model which seems not right to me..
I can place EF model classes in the infrastructure layer, but how do I reference them in the application layer? Do I need to have an interface for each model repository or is there any multiple dependency injection for same interface?
I want domain model to hold by business models and place EF models in infrastructure layer and use AutoMapper to map between them if necessary.
So what is the best practice to hold EF models so it won't break Onion architecture?
If you are using EF Core I do not see the need to have separate EF models.
What I usually do is to implement the domain model classes in the domain layer the way it supports my business logic the best. Then in the infrastructure layer you place the entity framework configuration classes using IEntityTypeConfiguration with generics.
This is exactly the way this is thought to be used in order to keep the domain model classes free of infrastructure concerns so that the domain model would never have to change even if you change the database implementation.
You can see a working example here in the EShopOnContainers reference project powered by Microsoft.
For instance, the Order aggregate is defined in the domain layer whereas the corresponding model configuration class for the EF Core is placed in the infrastructure layer.
Then everything is wired up as usual in the API project startup and the corresponding DbContext (OrderingContext) class in the infrastructure layer.
The infrastructure layer will have a dependency on the domain entities from the domain layer but not the other way around which is what you want to achieve in an onion architecture.