2010-09-02 4 views
8

E 'possibile (anche probabile) che io non stia completamente del tutto il concetto di "unità di lavoro". Fondamentalmente, lo vedo come una sorta di ampia transazione utilizzata in un ambiente orientato agli oggetti. Avvia l'unità di lavoro, interagisci con gli oggetti, esegui il commit o esegui il rollback. Ma come si analizzano le transazioni effettive negli archivi dati dietro quegli oggetti?Unità di lavoro con più origini dati?

In un sistema con un singolo DB e un ORM (come NHibernate) è facile. La transazione può essere gestita tramite l'ORM. Ma che dire di un sistema in cui i modelli di domini personalizzati stanno oscurando molte fonti di dati disparate? E non tutte queste fonti di dati sono database relazionali? (C'è molto lavoro sul file system da queste parti.)

In questo momento sono bloccato sull'idea che "semplicemente non è possibile mantenere una transazione attraverso un DB SQL2005, un DB SQL2000, un DB2 DB e il file system è tutto nella stessa operazione aziendale "atomica". " Quindi per ora è responsabilità degli sviluppatori del team (che generalmente lavorano indipendentemente l'uno dall'altro) per mantenere le transazioni manualmente nel codice. Ogni DB può avere transazioni corrette su di esso, ma l'operazione aziendale nel suo complesso viene controllata manualmente e bilanciata in ogni fase significativa del percorso.

Tuttavia, con l'aumento della complessità nel dominio e il turnover degli sviluppatori standard, questo approccio diventerà sempre più difficile e soggetto ad errori nel tempo.

Qualcuno ha qualche consiglio o esempio su come un dominio come questo potrebbe essere meglio indirizzato, o come è stato affrontato in precedenza? L'attuale "dominio" in questo caso è ancora molto nella sua infanzia, evolvendosi come prototipo per un giorno espandere e consumare/sostituire un ampio ecosistema di disparate applicazioni legacy. Quindi c'è molto spazio per riprogettazione e ri-factoring.

Per riferimento, una vista di 10.000 piedi del progetto al quale sto puntando attualmente è: Una vasta raccolta di piccole applicazioni client asimmetriche che chiamano un servizio centrale basato sui messaggi. Il servizio è l'ingresso nel "dominio core" e può essere pensato come una grande applicazione in stile MVC. Le richieste vengono fatte al servizio (proprio come "azioni") che vengono raccolte dai gestori (proprio come i "controllori"). Tutto procedurale va lì. Interagiscono con i modelli, che contengono tutte le regole aziendali. I modelli pubblicano eventi che gli ascoltatori ("servizi" - questa parte è ancora torbida nella progettazione e soggetti a miglioramenti) prendono e gestiscono interagendo con i repository (database x, database y, file system, email, qualsiasi risorsa esterna). Tutto allegramente dipendente di conseguenza.

Scusate per la verbosità :) Ma se qualcuno ha qualche consiglio, mi piacerebbe sentirlo. Anche (soprattutto) se quel consiglio è "il tuo design è brutto, prova questo invece ..." Grazie!

+1

Hai mai consultato il Distributed Transaction Coordinator? http://msdn.microsoft.com/en-us/library/ms684146(VS.85).aspx –

+0

@ Michael - Ho avuto fortuna usando TransactionScope/MSDTC con soluzioni SqlServer-only. Spanning attraverso il file system e altri RDBMS potrebbe essere più complicato. OP sta parlando di coordinare il lavoro su vari motori db, ecco perché non sto suggerendo MSDTC come risposta. –

risposta

9

In precedenza ho lavorato a un sistema in grado di ottenere questo risultato ed è abbastanza semplice. Poiché il tuo progetto è nelle sue fasi iniziali, forse questa potrebbe essere un'informazione utile per te. Sfortunatamente, non ho più accesso al codice, ma sono ancora a mio agio nel descrivere come ha funzionato.

Quello che avevo fatto era creare i miei repository usando un'implementazione generica del modello di repository. Il tipo di repository di base sarà sempre riferimento ai servizi e a UoW. Per motivi di discussione, chiameremo BaseRepository. "T" sarebbe limitato alle implementazioni di IEntity, che denotavano un oggetto dominio. Da BaseRepository, avevo creato un altro set di classi base per il compositing, come SqlBaseRepository, XmlBaseRepository, ecc.

L'UoW si preoccupa solo del fatto che qualcosa è del tipo BaseRepository, che è dove la funzionalità di base esisterà. La CUD di base (di CRUD) verrebbe rappresentata, fornendo gli equivalenti per Crea, Aggiorna ed Elimina.Ciò che ciascuno di questi elementi farebbe consisterebbe nel creare un delegato e inserirlo in una coda all'interno dell'UoW, trasmettendo anche informazioni sul tipo di transazione che avrebbe dovuto essere e sui dati appropriati necessari per completarlo. L'UoW avrebbe iniziato a mantenere un elenco di quali repository avrebbero dovuto essere coinvolti nella transazione, ma non gli importava di che tipo fosse. Efficacemente, fare la fila qui è come arruolarsi in una transazione.

Il BaseRepository ha definito un metodo astratto chiamato qualcosa come .ApplyChange(). Una volta .Commit() è stato chiamato su UoW, creerebbe un TransactionScope() e inizierà a chiamare i delagati nell'elenco, restituendo le informazioni a .ApplyChange(). L'effettiva implementazione di .ApplyChange() esiste nella base del repository specifico, ad esempio SqlRepositoryBase, ecc. E potrebbe essere sovrascritta anche dall'implementazione.

Dove è stato difficile, almeno per me, stava tornando indietro. Ho trattato solo un singolo database, ma a volte ho apportato modifiche basate su file. Ho aggiunto un metodo .RevertChange() e ho iniziato a tracciare lo stato originale e gli stati modificati in modo da poter applicare fondamentalmente un reverse-delta per tornare al punto in cui ero nello stack di file.

Vorrei poter essere più specifico sull'implementazione, ma è passato più di un anno da quando ho visto il codice ora. Posso dirvi che la base per il codice originale è nata dal libro .NET Domain-Driven Design with C#: Problem - Design - Solution di Tim McCarthy. Una grande quantità dell'implementazione del mio repository era basata sui suoi esempi, con una grande maggioranza della mia personalizzazione in arrivo sulle UoW e sulla loro implementazione.

Spero che questo aiuti, un po '! :-)

+0

Questo è molto utile, in realtà. Per essere onesti, penso che la raccomandazione del libro sarà la parte più utile a lungo termine. Forse è il momento di rallentare l'armeggiare e recuperare la lettura. Probabilmente sono al punto della mia carriera in cui quel libro e i libri su cui l'autore lo ha basato (in particolare il libro di Fowler, che ho rimandato per qualche tempo) saranno una buona base per andare avanti. Grazie! – David

+1

Nessun problema, David. Quel libro ha anche un progetto su CodePlex, che ho dimenticato di menzionare. Puoi almeno tirare giù la fonte e tirare le gomme. ;-) http://dddpds.codeplex.com/ –