Sollte Domain Ereignisse innerhalb oder außerhalb einer Transaktion erhöht werden?
-
11-10-2019 - |
Frage
In unserer Anwendung wir Domain-Ereignisse auslösen, wenn Änderungen etwas in dem Domänenmodell. Einige der Aufgaben, die von den Event-Handler ausgeführt werden, müssen innerhalb derselben Transaktion durchgeführt werden, der verwendet wurde, wenn das Ereignis ausgelöst wird, müssen andere Aufgaben außerhalb dieser Transaktion durchgeführt werden.
Beispiel:
Wenn ein Bestellposten zu einem Auftrag Einheit hinzugefügt wird, die OrderLineAdded Domain-Ereignis ausgelöst wird, ändert sich eine Domäne Ereignis den Zustand des Domänenmodell (so muss in derselben Transaktion ausgeführt werden), dann, wenn die Transaktion über die UI muss abgeschlossen ist aktualisiert werden.
Wie würden Sie dieses Problem angehen?
- Raise zwei Ereignisse, ein innerhalb der Transaktion, und ein außerhalb der Transaktion.
- Erhöhen Sie die Veranstaltung innerhalb der Transaktion, sondern verwenden Sie die Event-Handler eine Async Anfrage zu senden, um die Benutzeroberfläche zu aktualisieren?
Option 1 scheint verwirrend, da die Ereignisse Namen müssen irgendwie vermitteln sie in oder aus einer Transaktion, aber mit der Option 2-Handler der Domäne Ereignisses muss immer davon ausgehen, dass sie synchron von innerhalb einer Transaktion aufgerufen werden.
Vielleicht gibt es einen besseren Ansatz?
Lösung
Ich habe ein ähnliches Problem hat. Domain-Modell wurde die Veröffentlichung Ereignisse (unter Verwendung der Technik Udi Dahan hier beschreibt). Dann wurde mir klar, dass mein UI-bezogene Handler selbst aufgerufen werden, wenn etwas schief geht und Transaktion wird später wieder aufgerollt.
Dies mich beheben eingeführt andere Rolle für das System, eine andere Art von Event-Handler. I hat ITransactionalEventHadneler
und INonTransactionalEventHandler
. Der ehemalige wurden synchonously sofort in DomainEvents.Publish()
Methode aufgerufen. Letztere wurden die Warteschlange gestellt, sobald aufgerufen werden als Transaktion (mit System.Transactions Haken) begangen wird. Die Lösung funktionierte gut und war gut lesbar und wartbar.
Andere Tipps
Ich denke, beide Ansatz könnte gut sein, nur Stick auf den gleichen Ansatz in allen Teilen des Codes:
- Sie werden zwei benötigen (oder mehr) Event-Handler, eine für den Kontext des Domänenmodell, dass die innerhalb des Transaktionsbereich und andere (n) für die Hilfs Kontexten, wie die UI. Ihre Domain Code sollte etwa nicht, was andere Teile des Codes zu tun, nur teilen sie über die Änderung in den Domaindaten.
- Ihre Domain Code Ereignishandler Methode asynchrone Ereignisse an der Benutzeroberfläche oder andere Module senden. Die Domain-Ereignisse sollten synchron sein, sonst würden Sie zweiphasige Commits müssen Transaktionalität halten.
Ich persönlich mag die Option 2 mehr, weil es den Reiniger Domain Code hält und durch die asynchrone Kommunikation mit dem Kern und die anderen Module entkoppelt werden, damit Problemen in den externen Modulen wird nicht behindern die Funktionsweise des Kerns. Auf der anderen Seite kann es Umstände geben, in denen die Option 1 ist vorteilhafter.