Comunicazione / aggiornamenti tra unità di lavoro / contesti di strutture entità, in conflitto con le modifiche dell'utente

4

Sto sviluppando un'applicazione WPF usando Entity Framework per la mia comunicazione con il database. L'applicazione ha una gerarchia di schede in cui ogni scheda ha un contesto db. Ogni scheda consente all'utente di visualizzare alcuni oggetti particolari, apportare modifiche, salvare, aggiornare, chiudere o aprire schede per oggetti correlati.

Il mio punto cruciale è che alcune schede contengono informazioni che dipendono anche da altri oggetti, un oggetto O di tipo A può essere correlato ad altri oggetti A (o_1, ..., o_n) in una relazione genitore-figlio, dove io avere un indicatore grafico che mostra se la proprietà P in O ha lo stesso valore di P in tutti i figli di O, per esempio. Indicatore rosso significa che sono diseguali, verde significa che sono uguali.

La "sovrapposizione" tra le informazioni tra i contesti sarà solo in termini di presentazione, le diverse schede non si sovrapporranno le une alle altre cambiando i rispettivi dati.

Ora se ho aperto Tab per O e o_3, cambio P in o_3 e salvataggio, potrebbe essere necessario modificare anche l'indicatore nella scheda per O, ma poiché tale scheda ha il suo contesto db (ora obsoleto), il l'indicatore mostra ancora il vecchio valore, che potrebbe confondere l'utente.

Questo sembra un problema molto generale e comune considerando quante applicazioni hanno questa architettura.

Come risolveresti il problema? Vedo alcune soluzioni diverse ma imperfette / problematiche.

A. Rendere l'utente consapevole del fatto che le schede possono diventare "obsolete" quando si salvano altre persone. Sembra una perdita di problemi tecnologici.

B. Forza gli aggiornamenti delle schede correlate durante il salvataggio. Ciò sovrascriverebbe le modifiche dell'utente o dovrei creare un sistema (modello di repository?) che mantenga informazioni sulle modifiche dell'utente e media cosa aggiornare e cosa tenere, cosa dire all'utente e così via.

C. Indicare obsoleto: ness delle schede correlate. Sembra la soluzione pragmatica, ma l'utente è lasciato a chiedersi cosa sarebbe interessato se si aggiornasse la scheda manualmente e tutte le modifiche apportate dovessero essere eliminate

D. Comunicare la modifica all'altra scheda senza coinvolgere il contesto db. Questo potrebbe funzionare, ma potrebbe portare a problemi complicati introducendo uno stato che non è correlato al contesto db, nel complesso aumenterebbe la complessità

    
posta Mårten 03.09.2014 - 16:12
fonte

2 risposte

2

Nell'applicazione desktop in cui sto lavorando abbiamo risolto problemi simili introducendo un meccanismo di eventi, incentrato su un "Event Manager" globale. Abbiamo una manciata di "oggetti business principali" (~ 10 tipi diversi) e ogni volta che una finestra di dialogo cambia un oggetto business, genera un evento "change", incluso il tipo e l'ID dell'oggetto correlato (l'ID è anche la chiave primaria DB, abbiamo chiavi intere uniformi per tutti i nostri oggetti). Ci sono anche eventi "aggiungi" o "cancellati" per oggetti appena creati o cancellati.

Ora le finestre di dialogo usano lo schema del sottoscrittore del publisher, se sono "interessate" a ricevere notifiche sulle modifiche per un tipo di oggetto specifico, si registrano al gestore eventi, che quindi passerà le notifiche per il tipo specifico a ogni listener registrato .

Ma come risolve i problemi che hai menzionato? Bene, la risposta è: ogni finestra di dialogo può ora decidere da sé cosa fare quando ottiene un evento di cambiamento per un oggetto correlato. Ciò rende le modifiche e la gestione delle collisioni molto più semplici e gestibili come se un dialogo dovesse prendere decisioni per un'altra finestra di dialogo "genitore" o "figlio". Ad esempio, quando si riceve una notifica di modifica, una finestra di dialogo può verificare se l'ID negli eventi di modifica è uguale all'ID di uno degli oggetti che sta attualmente presentando e decide di aggiornare l'oggetto in questione dal DB. Oppure, se ci sono state modifiche in sospeso fatte a quell'oggetto dall'utente in una seconda finestra di dialogo, potrebbe presentare all'utente una sorta di finestra di dialogo "Risoluzione collisioni", eseguire alcune operazioni di collisione automatica o semplicemente notificare all'utente la collisione e lasciare lui si occupa di quello. Questo è in realtà ciò che hai citato sotto "B". Come deve essere la strategia di "risoluzione collisioni" dipende molto dalla quantità e dall'importanza dei dati, quanto possono perdere i dati nella "unità di lavoro" quando si implementa solo una strategia semplice come "l'ultima modifica vince", o se hai bisogno di uno strumento "confronta-e-unisce" molto sofisticato.

Si noti che questa gestione degli eventi funziona solo all'interno dell'applicazione locale, non abbiamo implementato una cosa del genere su client diversi, quindi quando un utente che lavora al client 1 cambia un oggetto, un secondo utente che lavora al client 2 ha sul display, è possibile che il client 2 mostri ancora i vecchi dati per un po 'di tempo. Lo scopo è semplicemente non confondere l'utente mostrando lo stesso oggetto in stati diversi simultaneamente sullo stesso schermo.

    
risposta data 03.09.2014 - 18:18
fonte
1

Penso che il vero problema qui sia che stai permettendo un dettaglio di implementazione (la relazione tra DBContext e schede di interfaccia) per limitare il tuo pensiero sull'esperienza utente della tua applicazione. Non c'è niente per legare la metodologia delle connessioni del database all'interfaccia. In effetti, per praticità e testabilità dovresti senz'altro separarli il più possibile. Il semplice atto di separare il livello dati dall'interfaccia e l'implementazione della logica come livello intermedio causerebbe l'evaporazione di questo problema.

C'è anche qualcosa che non capisco della tua seconda opzione - perché aggiornare le altre schede quando l'utente salva sovrascrive le loro modifiche? Sicuramente se lo fai ogni volta che un utente salva, allora non dovrebbe affatto sovrascrivere i loro dati? Se le dipendenze sono abbastanza forti che la modifica dell'articolo 2 nella scheda 3 sovrascrive l'articolo 1 nella scheda 1, è necessario tornare ai primi principi e ripensare la progettazione dell'interfaccia: gli utenti sorprendenti sono cattivi, gli utenti sorprendenti sovrascrivendo i dati inseriti in precedenza senza consentire la creazione è ovvio che questo accadrà è un importante no-no.

Con tutto ciò che ho detto, penserei a due cose: innanzitutto esperienza utente, seconda struttura dell'applicazione.

Se sto utilizzando un software e lo aggiorno, mi aspetto che il software rifletta il mio aggiornamento su tutta la linea. (Tangenziale ma importante per considerazioni architettoniche, mi aspetto anche che il software sia in grado di annullare tale modifica.)

Da questo possiamo immediatamente scartare le opzioni A e C dal tuo elenco. Nel caso C se apro una scheda e indica che è obsoleto, l'unica cosa che posso fare è aggiornarlo comunque.

Sono strongmente propenso a fare sempre più lavoro in modo che i miei utenti possano fare meno lavoro.

Pensare a B e D dipende dalla struttura dell'applicazione. Se è client-server, la tua logica di business è sul server? Se la logica aziendale è sul client, allora puoi andare per D perché hai già tutte le informazioni necessarie per aggiornare i dati adiacenti disponibili lì. Se si dispone della logica aziendale sul server, sarà necessario tornare al server per ricaricare i dati nelle altre schede.

Modificato per aggiungere: potresti voler fornire un qualche tipo di funzione di blocco, solo per impedire a due utenti di modificare la stessa cosa allo stesso tempo. Con un basso numero di utenti non devi preoccuparti troppo di avere un sacco di database o traffico di rete, quindi puoi farlo in modo abbastanza sicuro.

    
risposta data 04.09.2014 - 11:58
fonte

Leggi altre domande sui tag