Miglior schema di progettazione per due scenari specifici, il primo si inserisce perfettamente in un modello di Unità di lavoro (UoW)

0

Ho una domanda su quale sarebbe il miglior design pattern da usare. Ho 2 scenari specifici, il primo si inserisce perfettamente in un modello dell'Unità di lavoro (UoW). Il secondo è un po 'più laborioso. Fondamentalmente, in determinati scenari di business, ho bisogno di salvare alcuni dati anche se tutte le altre informazioni non riescono a salvare a causa (motivi che non includono il server del database che va giù).

Ad esempio, otteniamo informazioni sulle persone che hanno saldi pagati sul loro conto. Quindi la prima tabella in cui salviamo le informazioni è la tabella Pagamenti, prima di passare al salvataggio di altre entità incluse le righe di controllo. Tuttavia, consideriamo le righe di controllo meno importanti rispetto all'inserimento di un record relativo al pagamento effettuato. Utilizzando il tradizionale pattern UOW, il rollback non ci permetterebbe di impegnare il record di pagamento.

Quindi sono un po 'bloccato su come implementare un tale meccanismo senza avere più pattern nel nostro livello di dominio.

Ho anche considerato che i record importanti fossero il proprio UoW e quindi i record di controllo come UoW separato.

Quale sarebbe la via migliore da seguire?

Il nostro stack di base è C #, MVC, Entity Framework e Autofac

Qualsiasi guida sarebbe sicuramente apprezzata.

    
posta S-Unit 26.07.2016 - 21:00
fonte

2 risposte

0

Quello che stai cercando non è impossibile, ma la validità di farlo è un po 'discutibile. Per prima cosa ti darò una risposta diretta alla tua domanda, ma ti suggerisco di rivalutare se questa è una soluzione desiderabile.

What would be considered the better way forward?

Il problema non è un problema tecnico, ma quello di capire cosa vuoi fare.

  1. Consideri l'aggiornamento di pagamento e di controllo come una singola transazione.
  2. Consideri l'aggiornamento del pagamento e l'aggiornamento di verifica come transazioni separate.

(1) è quello che hai ora, la tua domanda ti sta chiedendo come ottenere (2).

So I'm a little bit stuck as to how I would implement such a mechanism without having multiple patterns in our domain layer.

Non vedo la difficoltà tecnica qui. Un'unità di modello di lavoro non vieta di avere transazioni separate. Ogni transazione ha lo stesso flusso di lavoro: aggiungi tutte le modifiche necessarie, quindi effettua il commit della transazione.

Ci sono due approcci qui. L'approccio migliore dipende dal tuo scenario specifico.

1
È possibile riutilizzare la stessa unità di lavoro (oggetto memoria) per eseguire sia l'aggiornamento del pagamento che l'aggiornamento di verifica. Tutto quello che devi fare è fare separare le due operazioni nel codice. Effettua tutta la logica di aggiornamento dei pagamenti, esegui il commit, esegui tutta la logica di aggiornamento del controllo, effettua il commit.

2
È possibile utilizzare diverse unità di lavoro (oggetti di memoria), una per i pagamenti e una per il controllo. Ciò comporta un sovraccarico maggiore per manipolare i due oggetti, ma rende più semplice impedire che la logica di aggiornamento dei pagamenti / audit aggiunga le sue modifiche alla transazione errata per errore.

Ci sono anche casi in cui gli aggiornamenti non possono essere separati senza creare altri problemi. Ad esempio, supponiamo che questa sia la tua logica di aggiornamento:

FooHandler.Update(myUOW);
BarHandler.Update(myUOW);

myUOW.Commit();

Ciascuno di questi gestori genera aggiornamenti sia di pagamento che di controllo. Se dovessi riutilizzare lo stesso oggetto UOW, saresti costretto a dividere la logica:

FooHandler.UpdatePayments(myUOW);
BarHandler.UpdatePayments(myUOW);

myUOW.Commit(); //Commit payment update

FooHandler.UpdateAudit(myUOW);
BarHandler.UpdateAudit(myUOW);

myUOW.Commit(); //Commit audit update

Non solo è più brutto, ma può anche ostacolare le prestazioni se i metodi sono pesanti in termini di risorse, probabilmente causando la necessità di dover ripetere parte del lavoro.

Invece, è meglio avere due oggetti separati, poiché puoi evitare di dover separare la logica:

FooHandler.Update(myPaymentUOW, myAuditUOW);
BarHandler.Update(myPaymentUOW, myAuditUOW);

myPaymentUOW.Commit();
myAuditUOW.Commit();

Ho omesso il try / catch che ci si aspetta di vedere attorno ai commit.

Come ultima menzione, e possibilmente un avvertimento, voglio concentrarmi sul commento di Telastyn:

Frankly, if you're auditing anything involving money, it should rollback the actual transaction too if the audit fails.

Ogni ragioniere / impiegato finanziario shoudl rabbrividisce al pensiero di voi che apportate modifiche ai dati senza registrare le modifiche in modo che possa essere rintracciato se necessario. Questo è esattamente ciò che si intende fare un audit.

Dubito strongmente che qualcuno, cliente / imprenditore, approvi il software finanziario che apporta modifiche ai saldi senza generare la traccia cartacea necessaria.

In secondo luogo, mi aspetto che i dati di audit vengano generati automaticamente dal sistema ogni volta che registra una modifica, contrariamente alla logica aziendale che ottiene l'autonomia per decidere se aggiungere aggiornamenti di verifica.

In terzo luogo, anche se questo potrebbe essere più un argomento semantico che pratico, ma se l'aggiornamento di controllo fosse veramente opzionale, dovresti riferirti ad esso come logging , non come auditing.

    
risposta data 20.08.2018 - 11:06
fonte
-2

Se si utilizza il modello di repository UOW / Generico è possibile includere un layer WCF per attivare un salvataggio e dimenticare quando la transazione di pagamento viene attivata su UnitOfWork.SaveChangesAsync (). Questo schema ha funzionato per il mio controllo ma è stato necessario creare un thread separato per non influire sull'applicazione.

    
risposta data 27.07.2016 - 20:20
fonte

Leggi altre domande sui tag