2

I have a web application being built using DDD and Onion architecture in .NET Core 5.

There are 4 layers:

  1. Domain layer - which contains domain models
  2. Application layer - which has core business logic and have reference to domain layer
  3. Infrastructure layer - which uses EF Core to retrieve and save data to Azure SQL, and it refers to the application layer
  4. API layer - which has controllers and refers to application and infrastructure 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.

  1. Placing models and mappings in Domain 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..

  1. Placing models in infrastructure layer

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?

RashmiMs
  • 129
  • 14

2 Answers2

2

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.

Andreas Hütter
  • 3,288
  • 1
  • 11
  • 19
  • There can me separate models for Domain and EF core. EF core usually holds models that adhere to tables created in database, where as Domain models can be combination of one or 2 tables or with more information if needed. Eg: Database can have 2 tables for order like Order table and Order status where as Domain object for Order may include both as Single Model as OrderInformation. – RashmiMs Dec 29 '20 at 05:22
  • And that is why both domain model and data model (here EFCore) are designed more or less individually. The Order aggregate does not care how many sql tables are used in the infrastructure to persist it's data. If an Aggregate has child entities those are usually stored in separate tables whereas value objects are usually flattened in the same table as the parent entity or even stored, for instance, as JSON if you prefer. – Andreas Hütter Dec 29 '20 at 07:08
  • Thanks @afh , that seems a solution for it. – RashmiMs Jan 04 '21 at 15:58
0

Well you can have your Infrastructure layer retrieve data from EF core and map it to your domain layer, you would have to have an interface for each repository that will return domain models. As for different implementations of the same interface you can always build some kind of factory that will handle that. Something like this answer.