DDD Bidirectionele associaties opslaan

Pagina: 1
Acties:

  • whoami
  • Registratie: December 2000
  • Laatst online: 16:54
Ik zit over het volgende na te denken;
Stel, je hebt een class Customer. Deze class bevat een collectie van Orders. Een Order heeft een verwijzing naar de Customer tot wie hij behoort.

Je hebt ook 2 repositories; een CustomerRepository en een OrderRepository. De CustomerRepository heeft een Save( Customer ) method die alle informatie van de Customer gaat persisteren. Die CustomerRepository gebruikt dan ook de OrderRepository om ieder Order van die Customer dat gewijzigd is (of nieuw gecreeërd) is, te gaan opslaan/updaten.
Tot zover geen probleem.
Echter, wat doe je met die Customer referentie in Order, in de OrderRepostory ?
Een OrderRepository heeft ook een Save( Order ) method. Wat als je beslist om ook hier te checken of de evt wijzigingen Customer moeten gepersisteerd worden ?

Ter illustratie:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void Save( Customer c )
{

     if( c.IsNew )
     {
           // insert customer
     }
     else if( c.IsDirty )
     {
           // update customer
     }

     foreach( Order o in c.Orders )
     {
            orderRepositoryObj.Save (o);
     }

     c.AcceptChanges();

}


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
public void Save( Order o )
{
       if( o.IsNew )
       {
             // insert order
       }
       else if( o.IsDirty )
       {
             // update order
       }

       customerRepositoryObj.Save (o.Customer);
}


Zoals je ziet, zitten we hier eigenlijk in een soort ‘oneindige lus’. De CustomerRepository savet de Customer, en roept de OrderRepository op, die de Orders gaat gaan saven, maar deze gaat dan ook weer de Customer gaan updaten.

Eigenlijk zou je in die CustomerRepository moeten aangeven dat die Customer niet meer dirty is voor je de Orders gaat gaan wegschrijven; echter, die IsNew en IsDirty properties zijn read-only, en de 'AcceptChanges' method gaat IsDirty en IsNew van de Customer, maar ook van alle andere gerelateerde objecten binnen die entity (de Orders dus) op false gaan zetten.
Ofwel zou de OrderRepository zich niet mogen bezighouden met het updaten/saven van de Customer die gerelateerd is aan dat Order.

https://fgheysels.github.io/


  • Orphix
  • Registratie: Februari 2000
  • Niet online
whoami schreef op maandag 10 april 2006 @ 20:21:
Ofwel zou de OrderRepository zich niet mogen bezighouden met het updaten/saven van de Customer die gerelateerd is aan dat Order.
Ik vind inderdaad dat dit niet mogelijk zou moeten zijn. Een Order->Customer is een n:1 relatie. Een Customer kan prima zonder Order bestaan. Een Order zonder Customer is niet mogelijk. Een order 'bezit' dus geen Customer. En zou deze ook niet mogen wijzigen. Op deze manier kan je alle n:1 en m:n relaties als read-only eigenschappen beschouwen van een entiteit.

Het voorkomen van deze loop kan of door middel van conventie (en discipline), of je laat je programmeertaal meewerken door enkel getters te definieeren, of const methodes toe te passen. Zodanig dat je een compile-error krijgt wanneer een dergelijke (ongewenste) actie wordt gedaan.

  • Kama
  • Registratie: Mei 2002
  • Laatst online: 22-12-2025

Kama

Game Coordinator

Wat je kunt doen is "ownership" definieren op je classes. Voor iedere class wijs je een owning class aan die verantwoordelijk wordt voor het saven. Deze owner saved dus bij het saven van zichzelf ook de instanties van classes die deze class "owned". Dus als je Customer saved, moet die ook alle saves afroepen op gerelateerde Orders. Tevens kun je via ownership ook "cascading delete" oid implementeren... (Dus: een instantie houdt op te bestaan als z'n owning class relatie geen instantie aan de andere zijde heeft).

Aangezien iets maar 1 owner heeft en alles wat bestaat een owner moet hebben, weet je zeker dat je alle instanties precies 1x tegenkomt.

Uiteraard moet je dan wel 1 global instance hebben die de top van je owning closure vormt.

drs. Kama


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

1) Je kunt uiteraard bijhouden welke objecten je al hebt gepersist. OR-mappers doen dit helemaal transparant voor je

2) beschrijf in je dao`s wat hun verantwoordelijkheden zijn. Jij gaat als je een order gaat saven toch ook niet controleren of de order.owner.vader.moeder.fiets.maker zijn voornaam is aangepast? Je moet dus in je DAO goed beschrijven wat zijn verantwoordelijkheden zijn en hoe diep er dus gepersist gaat worden. Dit is ook een van mijn problemen bij de DAO's die ik zie/maak: niemand zet er commentaar bij wat de reachability is.

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Zoals je het nu omschrijft is het niet oplosbaar. Je moet nl. de in-memory graph van alle objects opbouwen en die sorteren met een directional graph sort algorithme, bv topology sort via depth-first.

Je krijgt dan een lijst van entities die je moet saven en ze staan in de juiste volgorde. Dan zet je de inserts in de insertqueue, de updates in de update queue en executeert eerst de inserts en dan de updates.

Zoals je het nu wilt regelen lukt niet, omdat je de volgorde waarin alles gebeurt niet op dat niveau kunt bepalen.

Oh, en degene die hierboven roept dat je via ownership cascading deletes kunt implementeren: dat kan niet altijd, want soms heb je meerdere paths van entity A naar entity B, en bv niet alle instances van alle paths in memory.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • whoami
  • Registratie: December 2000
  • Laatst online: 16:54
EfBe schreef op dinsdag 11 april 2006 @ 13:54:
Zoals je het nu omschrijft is het niet oplosbaar. Je moet nl. de in-memory graph van alle objects opbouwen en die sorteren met een directional graph sort algorithme, bv topology sort via depth-first.

Je krijgt dan een lijst van entities die je moet saven en ze staan in de juiste volgorde. Dan zet je de inserts in de insertqueue, de updates in de update queue en executeert eerst de inserts en dan de updates.
Daar had ik ook al eens aan gedacht; een soort collection bijhouden die de entities bevat die dirty zijn.
Ik zal eens zoeken naar info over die sort algoritmen.

https://fgheysels.github.io/

Pagina: 1