Arbeitseinheit mit mehreren Datenquellen?

8

Es ist möglich (sogar wahrscheinlich), dass ich das Konzept einer "Einheit der Arbeit" nicht vollständig ausgeheckt habe. Im Grunde genommen sehe ich es als eine Art breite Transaktion in einer objektorientierten Umgebung. Starten Sie die Arbeitseinheit, interagieren Sie mit den Objekten, Commit oder Rollback. Aber wie läuft das auf die tatsächlichen Transaktionen in den Datenspeichern hinter diesen Objekten ab?

In einem System mit einer einzelnen DB und einem ORM (wie NHibernate) ist es einfach. Die Transaktion kann über das ORM gepflegt werden. Aber was ist mit einem System, bei dem die benutzerdefinierten Domänenmodelle viele verschiedene Datenquellen verdecken? Und nicht alle diese Datenquellen sind relationale Datenbanken? (Hier im Dateisystem ist viel getan.)

Im Moment bleibe ich bei der Idee, dass "man einfach keine Transaktion über eine SQL2005-DB, eine SQL2000-DB, eine DB2-DB und das Dateisystem im selben" atomaren "Geschäftsvorgang verwalten kann." Im Moment liegt es in der Verantwortung der Entwickler im Team (die im Allgemeinen unabhängig voneinander arbeiten), Transaktionen manuell im Code zu verwalten. Jede Datenbank kann über entsprechende Transaktionen verfügen, aber die Geschäftsoperation als Ganzes wird manuell überprüft und in jedem wichtigen Schritt ausgeglichen.

Mit zunehmender Komplexität im Bereich der Domänen- und Standardentwickler wird dieser Ansatz jedoch im Laufe der Zeit immer schwieriger und fehleranfälliger.

Hat jemand Ratschläge oder Beispiele dafür, wie eine solche Domain am besten angesprochen werden kann oder wie sie zuvor angesprochen wurde? Die eigentliche "Domäne" befindet sich in diesem Fall noch in den Kinderschuhen und entwickelt sich zu einem Prototyp, um eines Tages ein großes Ökosystem unterschiedlicher Altanwendungen zu erweitern und zu konsumieren. Es gibt also viel Raum für Neugestaltung und Neu-Faktorisierung.

Zur Veranschaulichung: Eine 10.000-Fuß-Ansicht des Designs, auf das ich momentan zusteuere, ist: Eine große Sammlung von kleinen, so dummen wie möglichen Client-Anwendungen, die einen zentralen nachrichtenbasierten Dienst aufrufen. Der Dienst ist der Einstieg in den "Domain-Kern" und kann als eine große Anwendung im MVC-Stil betrachtet werden. Anfragen werden an den Dienst gerichtet (ähnlich wie "Aktionen"), die von Handlern (ähnlich wie "Controller") abgeholt werden. Alles, was verfahren ist, geht dort hin. Sie interagieren mit den Modellen, die alle Geschäftsregeln enthalten. Die Modelle veröffentlichen Ereignisse, die Listener ("Dienste" - dieser Teil ist im Entwurf immer noch unklar und verbesserungswürdig) durch Interaktion mit Repositories (Datenbank x, Datenbank, Dateisystem, E-Mail, beliebige externe Ressourcen) aufnehmen und handhaben. Alles fröhlich dependency-injected.

Entschuldigung für die ganze Ausführlichkeit :) Aber wenn jemand einen Rat hat, würde ich es gerne hören. Sogar (besonders) wenn dieser Ratschlag "Ihr Entwurf ist schlecht, versuchen Sie es stattdessen ..." Danke!

    
David 02.09.2010, 17:16
quelle

1 Antwort

9

Ich habe vorher an einem System gearbeitet, das dies erreichen könnte, und es ist ziemlich einfach. Da sich Ihr Projekt in einem frühen Stadium befindet, könnte dies möglicherweise eine nützliche Information für Sie sein. Leider habe ich keinen Zugriff mehr auf den Code, bin aber immer noch in der Lage zu beschreiben, wie es funktioniert.

Ich habe meine Repositories mit einer generischen Repository-Musterimplementierung erstellt. Der Typ des Basisrepositorys wäre immer ein Verweis auf die Services und UoW. Aus Gründen der Diskussion nennen wir es BaseRepository. "T" wäre auf IEntity-Implementierungen beschränkt, die ein Domain-Objekt bezeichnen. Aus dem BaseRepository hatte ich einen weiteren Satz von Basisklassen für das Compositing erstellt, wie zum Beispiel SqlBaseRepository, XmlBaseRepository, etc.

Die UoW kümmert sich nur darum, dass etwas vom Typ BaseRepository ist, wo die Kernfunktionalität existieren würde. Grundlegende CUD (von CRUD) würde dargestellt werden und die Äquivalente für Erstellen, Aktualisieren und Löschen bereitstellen. Was jeder von ihnen tun würde, wäre, einen Delegaten zu erstellen und ihn in eine Warteschlange innerhalb der UoW ​​zu setzen, wobei er auch Informationen darüber mitteilt, welche Art von Transaktion er sein würde, und die entsprechenden Daten, die benötigt werden, um ihn abzuschließen. Die UoW würde damit beginnen, eine Liste der Repositories zu führen, die an der Transaktion beteiligt sein müssten, aber es war ihr immer noch egal, um welchen Typ es sich handelte. Effektiv ist es hier so, als würde man sich in eine Transaktion einreihen.

Das BaseRepository hat eine abstrakte Methode namens applyChange () definiert. Sobald .Commit () in der UOW aufgerufen wurde, würde es ein TransactionScope () erstellen und die Delagates in der Liste aufrufen und die Informationen an .ApplyChange () zurückgeben. Die tatsächliche Implementierung von .ApplyChange () existiert in der spezifischen Repository-Basis, d. H. Der SqlRepositoryBase usw., und könnte auch von der Implementierung überschrieben werden.

Wo es schwierig wurde, zumindest für mich, wurde zurückgedreht. Ich habe mich nur mit einer einzigen Datenbank befasst, aber manchmal wurden dateibasierte Änderungen vorgenommen. Ich fügte eine .RevertChange () -Methode hinzu und begann, den ursprünglichen Zustand und die geänderten Zustände zu verfolgen, so dass ich grundsätzlich ein umgekehrtes Delta anwenden konnte, um zu dem Punkt zurückzukehren, an dem ich mich im Dateistapel befand.

Ich wünsche mir, dass ich bei der Implementierung genauer sein könnte, aber es ist über ein Jahr her, dass ich den Code jetzt gesehen habe. Ich kann Ihnen sagen, dass die Grundlage für den ursprünglichen Code aus dem Buch .NET Domain-Driven Design mit C # stammte: Problem - Design - Lösung , von Tim McCarthy. Ein großer Teil meiner Repository-Implementierung basierte auf seinen Beispielen, wobei ein großer Teil meiner Anpassungen in den UoWs und deren Implementierung erfolgte.

Ich hoffe, das hilft, etwas! : -)

    
Joseph Ferris 03.09.2010, 12:18
quelle

Tags und Links