2010-11-12 16 views
6

Sto cercando di utilizzare NHibernate per gestire il livello di persistenza nella mia applicazione aziendale. In questo momento, mi chiedo come gestire modifiche/aggiornamenti simultanei in NHibernate o, più specificamente, come consentire a più istanze distribuite della mia applicazione di sapere che un utente ha modificato un determinato set di dati.NHibernate + modifiche simultanee: come ricevere notifiche delle modifiche?

Sono non in cerca di controllo delle versioni, vale a dire la coerenza di fronte a modifiche simultanee - So NHibernate supporta ottimistica concorrenza/pessimistica, e attualmente utilizzo concorrenza ottimistica via e la manipolazione del StateStateException.

Voglio solo sapere: Dato che l'utente A modifica una riga nel set di dati, come consentire all'utente B di sapere che si è verificato un cambiamento in modo che il set di dati possa essere ricaricato? In questo momento, sto pigro caricando una grande lista di clienti in una griglia usando NHibernate. Ora, se viene aggiunto un nuovo cliente, vorrei aggiungerlo alla griglia senza dover ricaricare nuovamente i dati interi: la prima preoccupazione dell'applicazione è rappresentata dalle prestazioni.

Inoltre, NHibernate gestirà correttamente le modifiche alle righe esistenti? In qualche modo rileverà le modifiche nel database sottostante e aggiornerà gli oggetti .NET in memoria in modo che l'accesso alle loro proprietà produrrà i valori aggiornati?

Avevo pensato di usare una tabella aggiuntiva, risparmiando gli ID di oggetti aggiornati con un timestamp per aggiornare gli elementi me stesso, ma se NHinbernate offre qualcosa a sé stante, che sarebbe una scelta molto Bett, ovviamente ...

risposta

3

Per questo sono necessarie notifiche/eventi a livello di database. Cioè, il motore di database deve fornire notifiche. Ad esempio, SQL Server has this feature. NHibernate funziona sull'applicazione, quindi tutto potrebbe potenzialmente do da solo sta interrogando il database per le modifiche (l'idea di utilizzare una tabella aggiuntiva sembra il polling), e sappiamo tutti che non va bene. Lo standard SysCache2 di NHibernate sfrutta SqlCacheDependencies per invalidare le voci della cache quando il database solleva una notifica, ma non sono a conoscenza che possa generare eventi da consumare dall'app stessa (che non sarebbe comunque utile, dato che le cache di 2 ° livello non lavorare con intere entità).

Un altro modo possibile per implementare questo sarebbe avere un listener di eventi NHibernate posizionare un messaggio broadcast su un bus dopo eventuali aggiornamenti, quindi ogni istanza dell'applicazione riceverebbe questo messaggio e lo recupererebbe dal database di conseguenza.

+0

Come al secondo suggerimento di Mauricio, è possibile impostare un intercettore NHibernate che cade una nota in qualcosa come uno System.Messaging.MessageQueue ogni volta che un inserire o aggiornare si verifica su una classe che ti interessa. –

0

Ho dovuto risolvere alcuni problemi simili sul mio attuale progetto SQLite Fluent NHibernate.

Per il rilevamento degli aggiornamenti del database, ho utilizzato uno System.IO.FileSystemWatcher. Vedere il codice di esempio in my answer to my own, similar, question. Inoltre, dai un'occhiata a un'altra risposta alla stessa domanda, che suggeriva di utilizzare NHibernate Interceptors.

Ho anche scaricato il mio DB in una griglia. Ogni volta che FileSystemWatcher rileva che il DB è stato aggiornato, chiamo la seguente domanda di criteri e aggiungo i nuovi record che restituisce a BindingList che è il DataSource per la mia griglia. (Ho appena risparmio il più alto ID dei nuovi record in una variabile privata)

/// <summary> 
    /// Return list of measurements with Id fields higher than id parameter 
    /// </summary> 
    /// <param name="id"></param> 
    /// <returns></returns> 
    public static IList<T> GetMeasurementsNewerThan(int id) 
    { 
     var session = GetMainSession(); 

     using (var transaction = session.BeginTransaction()) 
     { 
      var newestMeasurements = 
       session.CreateCriteria(typeof(T)) 
         .Add(Expression.Gt("Id", id)) 
         .List<T>(); 

      transaction.Commit(); 

      return newestMeasurements; 
     } 
    } 
Problemi correlati