1

I want to use domain-driven design in a new project. My first step was to eliminate model classes used exclusively by DAL project (Entity Framework Core) and instead use business models directly.

But during this step I encountered a problem of circular dependencies and where to put DbContext class.

Suppose I have two projects - business and data. Business project contains all the business logic and relevant entity models. Data project contains Entity Framework specific stuff - configurations, migrations and DbContext.

Problem comes from dependencies. Data project depends on business project for entity models (used by configurations and DbContext). Business project depends on data project for DbContext, which is used by the business logic. This project architecture creates a dependency cycle, which I'm not sure how to break.

I have thought of a couple (bad) solutions:

  • Move DbContext to business project

    • This would remove data project dependency from business project, but it also pollutes business project with persistence layer stuff.
  • Abstract DbContext with interface located in business project.

    • This would also remove data project dependency from business project. This interface would firstly need to expose all the DbSets of models persisted by the database, and secondly it would need to expose all the DbContext properties and methods used by business logic (at minimum SaveChangesAsync, possibly some other stuff). DbContext extension methods would also not work when using the interface.

How do you solve this dependency cycle when using this style of domain-drive design with Entity Framework?

  • None. You put the DB context outside of the domain, hidden behind a data repository interface used by the business logic. – Wiktor Zychla Oct 06 '20 at 07:30
  • Send your DDD business and data code here - 1 business + 1 business interface and 1 data + 1 data interface. We will modify it for you. – Asherguru Oct 06 '20 at 07:35
  • I do it like so: Data project has the data model, meaning classes that represent my database, and my business logic project has business objects, which are basically identical to data layer stuff, except that they contain logic. And in between Business and data is a mapping for each entity, then methods in the business logic load/ save data model objects and automatically map between each other using something like Automapper – MindSwipe Oct 06 '20 at 07:44
  • There is no need for any DbContext in your domain (business) layer. You can look at this article from Microsoft which describes how to separate your domain layer from the persistence layer using separate database configuration classes: https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-implementation-entity-framework-core – Andreas Hütter Oct 06 '20 at 20:17
  • Possible duplicate: https://stackoverflow.com/q/18109547/861716 – Gert Arnold Oct 17 '20 at 21:46
  • @WiktorZychla u do not need to use repositry patteren its a dead and dyinf format. – c-sharp-and-swiftui-devni Nov 28 '22 at 15:09
  • @c-sharp-and-swiftui-devni: it is not dead and never will be. Entity framework is just one of many ways to access the data. Not all the data come from relational databases. There are still cases then where repositories make sense. Whether or not mix repos with ef is another story. But your statement is just too bold. – Wiktor Zychla Nov 29 '22 at 06:11

1 Answers1

0

You should consider only passing domain entities to the repositories in the persistence layer, so that you have 3 layers

-Application layer ( what your calling business layer. This is composed of coordination services)

-Domain Layer ( where domain entity classes live)

-Persistence Layer ( where repositories are implemented and your persistence entities live. Here is where mapping between domain-to-persistence model occurs, and visa versa)

Your repositories interfaces should be defined in the domain layer, whereas within the persistence layer it references the domain layer)

Judy007
  • 5,484
  • 4
  • 46
  • 68