2016-07-20 23 views
3

Ich versuche, Kaufdomäne mit CQRS & DDD zu modellieren, ich weiß, dass ich Ereignisse in Domäne auslösen, aber ich weiß nicht, wo ich sie registrieren, wenn ich Befehle verwende. Sollen Event-Handler in Command-Handlern registriert werden? oder vielleicht habe ich etwas falsch verstanden. Das ist mein Prozess Kannst du helfen, es richtig zu modellieren?Registrieren EventHandler in CQRS

Bestellvorgang abschließen Befehl wird erteilt, als Befehlshandler die Bestellung beendet (Auftrag aus dem Repository abrufen, Status ändern und zurück in db speichern), abgeschlossenes Ereignis tritt im Domänenmodell auf, dann findet der Ereignishandler diese Reihenfolge unter Verwendung der ID mit Werbebuchungen, Kontaktinformationen für Lieferanten finden (z. B. E-Mail oder sogar externe Services) und benachrichtigt ihn über neue Bestellungen.

Meine Befehle & Command Handler sind in Application Layer (Event Handler sollte hier auch sein?). Domänenmodell, Ereignisse und IR-Repositorys in Domänenebene. Repository-Implementierungen in der Infrastrukturschicht.

Domain Model (übersprungenen die meisten Eigenschaften):

public class PurchaseOrder 
{ 
    public PurchaseOrder(int purchaseOrderID, int supplierID, bool isOrderFinalized) 
    { 
     PurchaseOrderID = purchaseOrderID; 
     SupplierID = supplierID; 
     IsOrderFinalized = isOrderFinalized; 
    } 
    public int PurchaseOrderID { get; private set; } 
    public int SupplierID { get; private set; } 
    public bool IsOrderFinalized { get; private set; } 

    public static PurchaseOrder CreateNew(int supplierID) 
    { 
     return new PurchaseOrder(0, supplierID, false); 
    } 

    public void FinalizeOrder() 
    { 
     IsOrderFinalized = true; 
     DomainEvents.Raise(new PurchaseOrderFinalized(PurchaseOrderID)); 
    } 
} 

FinalizePurchaseOrder Befehl

public class FinalizePurchaseOrder : ICommand 
{ 
    public FinalizePurchaseOrder (int purchaseOrderID) 
    { 
     PurchaseOrderID = purchaseOrderID; 
    } 
    public int PurchaseOrderID { get; private set; } 
} 

Befehl Handler

public class PurchaseOrdersCommandHandler : ICommandHandler<FinalizePurchaseOrder> 
{ 
    public void Handle(FinalizePurchaseOrder command) 
    { 
     var purchaseOrder = purchaseOrderRepository.FindByID(command.PurchaseOrderID); 
     // Should i register event handler here? 
     // DomainEvents.Register<PurchaseOrderFinalized>(PurchaseOrderFinalizedHandler); 
     purchaseOrder.FinalizePurchaseOrder(); 
     purchaseOrderRepository.Save(purchaseOrder); 
    } 
} 

Veranstaltungs- und Event-Handler wie folgt aussieht:

public class PurchaseOrderFinalized 
{ 
    public PurchaseOrderFinalized(int purchaserOrderID) 
    { 
     PurchaseOrderID = purchaseOrderID; 
    } 
} 

public void PurchaseOrderFinalizedHandler (PurchaseOrderFinalized evt) 
{ 
    // TODO: Get PurchaseOrder with its line items, and notify supplier about new order 
} 

Antwort

3

Sollen Ereignishandler in Befehlshandlern registriert werden?

Nicht, es sei denn, sie sind dynamisch, nein. Sie würden sie normalerweise in Ihrer Anwendung CompositionRoot verdrahten. Die Idee ist, dass die gesamte Verkabelung stattfindet, wenn Ihre App geladen wird und bevor sie "fertig" ist.

Wo registrieren Sie Ihre Befehlshandler? Sie sollten Ihre Ereignishandler an derselben Stelle registrieren.

[UPDATE]

Ein Beispiel finden Sie https://github.com/gregoryyoung/m-r/blob/master/CQRSGui/Global.asax.cs

+0

Ich habe noch keine Befehlshandler registriert, ich habe nur Domänen- und Anwendungslayer und ich verwende Unit-Tests für einige Tests. Ich habe über CompositionRoot gelesen, also habe ich es im Falle von MVC ich werde Command & Event Handler in global.asax registrieren, ich habe gesehen, Beispiel Leute NServiceBus zu registrieren und senden Befehl/Ereignisse, bin ich richtig, dass dies auch DI ist Container? – QuietNaN

+0

NServiceBus ist kein DI-Container, sondern ein Servicebus. Wenn du gerade anfängst, würde ich überhaupt keinen DI-Container benutzen, sondern ihn reinbringen, wenn Pure DI ein Problem wird, sonst ist es einfach eine andere Sache zu lernen. – tomliversidge

+0

Verstanden, kannst du mir ein paar Links geben, wo ich hin kann ein Blick auf Code-Beispiel, wo Command/Event-Handler registriert sind (ohne nservicebus) in CompositionRoot und wie sie in der Anwendung verwendet werden. Ist es empfehlenswert, dafür einen Servicebus zu benutzen? – QuietNaN

0

Sie sollten Udi Dahan Präsentation überprüfen auf Reliable Messaging.

Die typische Architektur queue/Eventbus der Nachricht umfasst in der Regel etwas Aroma. Ihre Event-Handler registrieren beim Start ihre Abonnements für Ereignisse mit dem Bus. Wie @tomliversidge hervorhebt, wird dies in der Regel im Kompositionswurzel sein.

Wenn Sie die Änderungen an Ihren Aggregaten speichern, speichern Sie auch die DomainEvents, die von diesem Befehl ausgelöst wurden. Beide Schreibvorgänge finden in der gleichen Transaktion im selben Datensatz statt. So haben beide Erfolg oder beide versagen.

Wenn die Transaktion fehlschlägt, hat sich das Datenmodell nicht geändert, und niemand muss über irgendetwas informiert werden - melden Sie den Fehler wie üblich an den Client und gehen Sie mit Ihrem Leben weiter.

Wenn der Befehl erfolgreich ist, müssen wir die Veröffentlichung der Ereignisse veranlassen.Dies ist eine grundsätzlich asynchrone Operation - alle anderen Schreibvorgänge, die von Event-Handlern in das Buch geschrieben werden, befinden sich in ihren eigenen Transaktionen.

Die natürliche Sache zu tun ist, dass Ihr Command-Handler eine Aufgabe plant, um die Ereignisse auf dem Bus zu veröffentlichen. Nachdem die Aufgabe geplant wurde, kehrt die Befehlsroutine zurück (es ist nicht wichtig, wann die Aufgabe ausgeführt wird).

Aber da die Ereignisse im Buch der Aufzeichnung sind, können Sie sie jederzeit wieder veröffentlichen.

+0

Vielen Dank für Ihre Antwort, ich werde Präsentation von zu Hause aus überprüfen, Vimeo ist an meinem Arbeitsplatz blockiert. – QuietNaN