Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Foreign key between aggregate roots

I understand the concept of aggregate root and I know that one aggregate root must reference another by identity ( http://dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_2.pdf ) so what I don't get is how can I force Entity Framework to add a foreign key constraint between two aggregates?

Lets suppose I have a simplified domain:

public class AggregateOne{
    [Key]
    public Guid AggregateOneID{ get; private set;}
    public Guid AggregateTwoFK{get; private set;}
    /*Other Properties and methods*/
}

public class AggregateTwo{
    [Key]
    public Guid AggregateTwoID{get; private set;}
    /*Other Properties and methods*/
}

With this domain design, Entity Framework doesn't know that there is a relationship between AggregateOne and AggregateTwo and consequently there is no foreign key at the generated database.

like image 327
Julián Yuste Avatar asked Oct 16 '13 17:10

Julián Yuste


1 Answers

In DDD, EF doesn't exist. Domain relationships are not the same as database relationships. Don't try to mix EF with domain modeling, they don't work together. So in a nutshell, what you have there is not DDD, just plain old relational db masquerading as DDD. EF would be used by the Repositories and would care about persisting one Aggregate Root (AR).

Two ARs can work together, however you need to model the process according to the domain. EF is there to act as a db for the app, it's concerned with persistence issues and shouldn't care about the Domain. Persistence is all about storage and not about reflecting domain relationships (the EF entity is not the domain entity although they can have the same name and can look similar. The important detail is that both belong to different layers and handle different issues). The Domain repositories care only to persist the AR in a way that can be easily restored when it will change. If more AR need to be persisted together, embrace eventual consistency and learn how to use a service bus and sagas. It will greatly simplify your life (consider it a kind of implementation for the unit of work pattern).

For querying, the most clean and elegant way is to generate/update a read model suitable for the querying use cases and this is usually done after a domain event tells the 'world' that something changed in the Domain.

Doing DDD right is not straightforward and it's very easy to fall into the trap, believing that you apply DDD when in fact you're just CRUD ing away, using DDD terminology. Also IMO CQRS is a must with DDD if you like an easy life.

Understand the domain without rushing it and being superficial, identify the bounded contexts, model the domain concepts and their use cases (very important!!!), define repository interfaces as you need them, and implement the repositories only when there's nothing else left to do (the real repos, in the mean time you can use fake ones like in memory repos - they're very fast to implement and your app being decoupled means it shouldn't care about how persistence is implemented, right?). I know it sounds weird, but this how you know you have a maintainable DDD app.

The point of implementing the repositories last is to really decouple the app from the persistence details and also to have defined the expectations(repository methods) the app has from persistence. Once defined, you can write tests :D then implement the repositories. The bonus is that you get to focus only on repo implementation is isolation and when the all tests pass, you know everything works as it should.

like image 104
MikeSW Avatar answered Oct 26 '22 18:10

MikeSW