6

Hintergrund: Ich habe eine Person Domain-Objekt. Es ist eine aggregierte Wurzel. Ich habe einen Teil der Klasse darunter aufgenommen.Domain Driven Design - Umgang mit Updates für Teile Ihrer aggregate Wurzeln

Ich Belichtung Methoden, um die Objekte Verhalten durchzuführen. Um beispielsweise ein BankAccount hinzuzufügen, habe ich die AddBankAccount() -Methode. Ich habe nicht alle Methoden der Klasse einbezogen, aber es genügt zu sagen, dass jede öffentliche Eigenschaft mit einer Methode aktualisiert werden muss.

Ich werde ein IPerson-Repository erstellen, um die CRUD-Operationen zu behandeln.

public interface IPersonRepository 
{ 
    void Save(Person p); 
    //...other methods 
} 

FRAGE: Wie kann ich feststellen, das Repository, die aktualisiert werden Felder müssen, wenn wir eine vorhandene Person aktualisieren? Wenn ich beispielsweise einer vorhandenen Person ein Bankkonto hinzufüge, wie kann ich diese Informationen dem Repository mitteilen, wenn repository.Save() aufgerufen wird?

Im Repository ist es einfach zu bestimmen, wann eine neue Person erstellt wird, aber wenn eine existierende Person existiert und Sie Felder auf dieser Person aktualisieren, bin ich nicht sicher, wie dies dem Repository mitgeteilt werden soll.

Ich möchte nicht mein Person-Objekt mit Informationen darüber, welche Felder aktualisiert werden, verschmutzen.

Ich könnte separate Methoden auf dem Repository wie .UpdateEmail(), AddBankAccount() haben, aber das fühlt sich an wie Overkill. Ich möchte eine einfache .Save() -Methode für das Repository und es bestimmt, was in irgendeiner Weise aktualisiert werden muss.

Wie haben andere diese Situation gehandhabt?

Ich habe das Web und stackoverflow gesucht, aber nichts gefunden. Ich muss nicht richtig suchen, denn das scheint etwas Einfaches zu sein, wenn es um das Beharren innerhalb des DDD-Paradigmas geht. Ich könnte auch :-)

auf meinem Verständnis von DDD weg seine
public class Person : DomainObject 
{ 
    public Person(int Id, string FirstName, string LastName, 
     string Name, string Email) 
    { 
     this.Id = Id; 
     this.CreditCards = new List<CreditCard>(); 
     this.BankAccounts = new List<BankAccount>(); 
     this.PhoneNumbers = new List<PhoneNumber>(); 
     this.Sponsorships = new List<Sponsorship>(); 
    } 

    public string FirstName { get; private set; } 
    public string LastName { get; private set; } 
    public string Name{ get; private set; } 
    public string Email { get; private set; } 
    public string LoginName { get; private set; } 

    public ICollection<CreditCard> CreditCards { get; private set; } 

    public ICollection<BankAccount> BankAccounts { get; private set; } 

    public ICollection<PhoneNumber> PhoneNumbers { get; private set; } 

    public void AddBankAccount(BankAccount accountToAdd, IBankAccountValidator bankAccountValidator) 
    { 
     bankAccountValidator.Validate(accountToAdd); 

     this.BankAccounts.Add(accountToAdd); 
    } 

    public void AddCreditCard(CreditCard creditCardToAdd, ICreditCardValidator ccValidator) 
    { 
     ccValidator.Validate(creditCardToAdd); 

     this.CreditCards.Add(creditCardToAdd); 
    } 

    public void UpdateEmail(string NewEmail) 
    { 
     this.Email = NewEmail; 
    } 
+0

Hallo, ich sehe niemand wirklich Ihre Frage beantwortet. Nun, zumindest glaube ich nicht, dass "ORM verwenden" eine Lösung ist. Was hast du am Ende gemacht? –

Antwort

2

Es ist ein Beispiel für Repository-Schnittstelle von S#arp Architecture Projekt. Es ähnelt PoEAA Data Mapper, weil es auch CRUD-Operationen verwendet.

public interface IRepositoryWithTypedId<T, IdT> 
{ 
    T Get(IdT id);  
    IList<T> GetAll();  
    IList<T> FindAll(IDictionary<string, object> propertyValuePairs);  
    T FindOne(IDictionary<string, object> propertyValuePairs);  
    T SaveOrUpdate(T entity);  
    void Delete(T entity);  
    IDbContext DbContext { get; } 
} 

Wie Sie sehen, gibt es keine Update-Methode für bestimmte Eigenschaften einer Entität. Die gesamte Entität wird als ein Argument in die Methode SaveOrUpdate bereitgestellt.

Wenn Eigenschaften Ihrer Domäne Entität aktualisiert werden, sollten Sie Ihre Unit of Work sagen, dass Unternehmen ‚schmutzig‘ und sollte in den Speicher (zB Datenbank)

PoEAA Unit of Work

Sie verschmutzen sollten nicht Ihre Person-Objekt gespeichert werden mit Informationen über aktualisierte Felder, aber es wird benötigt, um Informationen zu verfolgen, wenn die Entität aktualisiert wird.

Möglicherweise gibt es Methoden der Klasse DomainObject, die "Einheit der Arbeit" mitteilen, wenn die Entität "neu", "schmutzig" oder "gelöscht" ist. Und dann kann Ihre UOW selbst richtige Repository-Methoden aufrufen - 'SaveOrUpdate' oder 'Delete'.

Trotz der Tatsache, dass moderne ORM Frameworks wie NHibernate oder EntityFramework ihre eigenen Implementierungen von 'Unit of Work' haben, neigen die Leute dazu, ihre eigenen Wrapper/Abstraktionen für sie zu schreiben.

+0

Vielen Dank für Ihre Kommentare, sehr geschätzt!. Leider weiß ich immer noch nicht, wie mein Personenobjekt das Repository darauf aufmerksam machen kann, dass eine Kreditkarte hinzugefügt wurde und gespeichert werden muss oder dass die E-Mail aktualisiert wurde und nur aktualisiert werden muss. Mein Person-Objekt enthält viele andere Objekte, aber in Wirklichkeit werden sie mehreren Datentabellen zugeordnet. – RDotLee

+1

Verwenden Sie ein ORM? Was verwenden Sie, um mit DB in Ihren Repositories zu interagieren? Es kann allgemein zwei Optionen geben: ** 1st ** -> Wenn CreditCard ein Kind des aggregierten Stammes ist und ohne Person keinen Sinn ergibt, dann sollten Sie Person (Personentabelle in DB) aktualisieren/erstellen und dann die Sammlung aktualisieren von CreditCards (CreditCards-Tabelle in DB) mit PersonRepository. ** 2nd ** -> Wenn CreditCard eine Entität ist, die ohne Person Sinn macht, dann sollten Sie CreditCard mit ihrem eigenen CreditCardRepository erstellen/aktualisieren und dann Person mit PersonRepository erstellen/aktualisieren. –

+0

Nochmals vielen Dank für Ihre Kommentare. In Ihrem ersten Szenario, was ich habe Schwierigkeiten zu verstehen ist, wie das PersonRepository weiß, dass eine Kreditkarte hinzugefügt wurde und eingefügt werden muss. Oder wie eine Kreditkarte geändert wurde und aktualisiert werden muss. – RDotLee

0

Was ich tue, dieses Problem zu lösen, ist das Hinzufügen einer Schnittstelle zu meinen Domain-Objekten:

interface IDirtyTracker { 
    bool IsDirty {get;} 
    void MarkClean(); 
    void MarkDirty(); 
} 

Die Basis DomainObject Klasse IDirtyTracker implementieren könnte, und dann usw. Repositories IsDirty verwenden könnten um zu überprüfen, ob es schmutzig oder sauber.

In jedem Setter, der eine Änderung macht:

void SetValue() { 
    this._value = newValue; 
    this.MarkDirty(); 
} 

Dies ist Ihnen nicht feinkörnig Prüfung, aber es ist ein einfacher Weg, um einige unnötige Aktualisierungen auf Repository-Ebene zu vermeiden.

Um dies ein wenig einfacher zu machen, könnte eine GetPropertiesToIncludeInDirtyCheck Methode hinzugefügt werden, die eine Liste von Eigenschaften abrufen würde, die überprüft werden müssen.

interface IDirtyTracker { 
    IENumerable<Object> GetPropertiesToIncludeInDirtyCheck(); 
} 
Verwandte Themen