Le migliori pratiche per ottenere l'ultimo record inserito nel DB

6

Io e un paio di colleghi stiamo discutendo sul seguente caso:

In una tabella OrderStatus teniamo traccia di tutti gli stati che un ordine attraversa nel tempo, inclusi "Pending" , "Available" , "Returned" , ecc. C'è un campo timestamp nella tabella per tenere traccia di quando ogni stato è stato aggiunto. Tuttavia, ci sono due stati che possono essere aggiunti esattamente allo stesso tempo, uno dopo l'altro, nel qual caso entrambi possono avere esattamente lo stesso timestamp (inclusi i millisecondi). In un'altra parte del codice, dobbiamo verificare quale sia l'ultimo stato in cui è stato impostato un ordine, e dal momento che stiamo ordinando in base al timestamp, possiamo facilmente ottenere il record sbagliato dal database.

La tabella ha una chiave primaria IDENTITY(1,1) , e i miei colleghi pensano che dovremmo ordinare usando quella colonna, dal momento che ti darà sempre l'ultimo record aggiunto alla tabella.

Mi sento come una colonna IDENTITY dovrebbe essere annullata di qualsiasi significato e quindi non dovrebbe essere usata per alcun ordinamento, e preferirei fare un Thread.Sleep(1) per assicurarmi che i timestamp siano diversi e possiamo continuare a ordinare usando quel campo .

Quale pensi sia la migliore pratica in questo caso?

    
posta Antrim 15.01.2016 - 16:57
fonte

4 risposte

5

Utilizza valori di stato numerici in cui il valore più alto rappresenta lo stato più alto. Aggiungi questo al tuo indice in ordine decrescente. Quindi ritirare il risultato ordinato dal timestamp e lo stato in ordine decrescente. In questo modo viene sempre restituita la voce con la progressione più lontana.

    
risposta data 15.01.2016 - 17:50
fonte
1

Un approccio migliore sarebbe due mantenere due tabelle, corrente e cronologia. La tabella corrente sarebbe sempre l'ultimo aggiornamento. L'altra tabella sarebbe una tabella di cronologia, che sarebbe sempre solo inserti e letture. Se si desidera ottenere l'ultimo record, interrogare la tabella corrente. Se non permetti letture sporche sarà sempre l'ultimo record. Se hai bisogno della cronologia, effettua una query nella tabella della cronologia e ordina il PK.

Per la tabella corrente si desidera mantenere un timestamp in modo che se qualcuno aggiorna il record dopo averlo letto, è possibile gestire il conflitto in modo appropriato prima di effettuare l'aggiornamento. Per la tabella della cronologia si sta sempre inserendo quindi nessun controllo è necessario. Se lo desideri, puoi gestire gli inserimenti cronologici con un trigger dalla tabella corrente.

Nel tuo esempio:

  • ORDINA (CORRENTE)
  • ORDER_HISTORY (HISTORY)

Ciò renderebbe la logica semplice.

    
risposta data 15.01.2016 - 17:09
fonte
1

Sembra che un approccio di sourcing di eventi sarebbe utile qui

link

In sostanza, ogni volta che aggiorni l'oggetto, lo carichi, aggiungi l'evento alla cronologia e salva tutto.

Quando salvi l'oggetto, controlli che nessun altro abbia aggiornato la cronologia nel frattempo. Se lo sono, ricostruisci l'oggetto dalla nuova cronologia e riprova ad aggiungere il tuo evento

In alternativa puoi bloccare l'oggetto per far sì che altri eventi attenderanno il completamento.

Questo è superiore a cose come le colonne di autoincremento perché garantisce che gli eventi vengano elaborati in ordine, non solo salvati in un ordine.

Tuttavia, nel tuo caso particolare, mi sembra che il tuo stato sia una funzione degli eventi accaduti. Invece di avere lo stato letto dall'ultimo evento, rendilo un calcolo basato su tutti gli eventi verificatisi.

In questo caso, non ti importa davvero quale evento è accaduto per primo, o se due sono accaduti allo stesso tempo.

es

Dì che hai "selezionato l'ordine" e "il controllo del credito cliente è passato"

concettualmente entrambi possono succedere allo stesso tempo, ma lo stato potrebbe essere

'non selezionato' - nessun evento selezionato

'controllo credito in sospeso' - evento selezionato ma nessun evento di controllo credito

"pronto per la consegna" - sia selezionato che con credito controllato

    
risposta data 15.01.2016 - 17:09
fonte
1

Il tuo collega ha ragione. Ordina con la chiave primaria. La chiave primaria è non priva di significato. Identifica ogni riga nella tabella. È numerico, il che implica l'ordine in cui sono stati creati i record.

Non si adatta perfettamente alla terminologia del tuo dominio aziendale, ma non trascura la soluzione semplice ed ovvia per ragioni ideologiche, specialmente quando questa soluzione richiede poco più di una clausola sort in una query SQL.

    
risposta data 17.01.2016 - 14:03
fonte

Leggi altre domande sui tag