I am trying to implement common DDD-based entity using Entity Framework Core. I have 2 separated databases, external and internal, which shares common table models and logic in some places. Ive tried to implement it that way:
public abstract class EmployeeBase
{
public Guid Id {get;}
public string Name {get; protected set;}
public Guid DepartmentId {get; protected set;}
public DeparmentBase {get; protected set;}
public void DomainMethod1() {...}
public void DomainMethod2() {...}
}
public class InternalEmployee : EmployeeBase
{
}
public class ExternalEmployee : EmployeeBase
{
}
public abstract class DepartmentBase
{
public Guid Id {get;}
public string Name {get; protected set;}
public ICollection<EmployeeBase> Employees {get; protected set;}
public void DomainMethod1() {...}
public void DomainMethod2() {...}
}
public class InternalDepartment : DepartmentBase
{
}
public class ExternalDepartment : DepartmentBase
{
}
Is it even possible to to that in entity framework core? I can not find the way to configure it using FluentAPI. Can anyone help? I am also not sure if it is a good idea to implement domain logic in abstract classes with nested properties of abstract type as well. Is there any better alternative? Thank you in advance!ent
CodePudding user response:
Is it even possible to to that in entity framework core?
Yes it is, documentation is here: https://docs.microsoft.com/en-us/ef/core/modeling/inheritance
I am also not sure if it is a good idea to implement domain logic in abstract classes with nested properties of abstract type as well. Is there any better alternative?
You are confusing DDD entities (domain model) with EF entities (persistence model).
Implementing domain logic in an abstract class with nested abstract properties is not a problem. What is a problem is doing that in an EF model, as it puts lots of stress on the object-relational mapping, especially if you have two back-end databases.
What an ORM (such as EF core) does is translating operations on objects into the relational world, and vice-versa. They usually manipulate POCO objects with as few logic as possible inside, because they are symbols: they represent, in the object world, database concepts, such as tables, rows, columns, indexes, etc ...
You can use the same business-persistence model if your application is designed with a domain-first approach. In that situation, the ORM is only responsible to persist the domain state as-is and the database structure follows by design the domain model. However, this model can become very complex, because it must both model the business logic and respect database design good practices. It only works if your business model is trivial.
Here, you have constraints on your database structure (two databases) and a complex domain model (with abstract/polymorphism), so you are not free to use your persistence layer a simple "save my domain state" library. You should split your concerns into different models:
- One persistence model per database, with anemic POCO and no abstract classes or properties
- One domain model with abstract classes and properties, implementing your domain logic
You may then implement an adapter between the models, with a repository pattern:
- https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design
- https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-implementation-entity-framework-core