La crisi d’identità di SQL Server

by Luca Baldini on 7 maggio 2013

La scorsa settimana abbiamo ricevuto una richiesta di assistenza che segnalava un possibile problema relativo ai campi contatore. Il testo della domanda era il seguente:

Inserisco un record in una tabella che ha un campo contatore; nella istruzione di Insert ho usato la funzionalità di Instant Developer che mi fornisce il valore del campo contatore dopo l’inserimento. Però non sembra funzionare correttamente.

Avevamo già ricevuto richieste simili in passato e anche questa volta la causa del problema è la stessa: la presenza di un trigger che dopo il salvataggio della nuova riga esegue una insert su un’altra tabella, anch’essa dotata di un campo contatore. Infatti per recuperare il valore in questione dopo uno statement di insert, le applicazioni sviluppate con Instant Developer utilizzano la proprietà @@IDENTITY, ma in questo caso particolare il risultato ottenuto non è corretto. Questo “problema” è noto a chi utilizza SQL Server, tanto da avere un nome specifico: Identity Crisis.

Alcuni di voi conoscono già il problema e in passato ci hanno chiesto perché non utilizziamo la funzione SCOPE_IDENTITY() per risolverlo. Purtroppo, come segnala Microsoft, in alcuni casi le funzioni @@IDENTITY e SCOPE_IDENTITY() possono restituire valori non corretti. Il bug è chiuso ma la correzione è presente solo in SQL Server 2012:

[...] that this bug is fixed in SQL Server 2012, but not in older versions, and that they will probably not provide a patch for older versions of SQL Server because of the risk of regression bugs.

Se avete a che fare con contatori e trigger di questo tipo, avete una sola strada da percorrere: rileggere il valore dell’ultima riga inserita identificandola mediante altri campi. È una soluzione scomoda, certo, ma è l’unica che può darvi una certezza.

Se invece dovete sviluppare una nuova applicazione voglio darvi un consiglio diverso. Infatti l’identity crisis non è l’unico problema legato all’uso dei contatori. Ad esempio, la sincronizzazione bidirezionale di dati generati da applicazioni mobile offline diventa problematica, perché i valori dei campi contatore creati nei dispositivi potrebbero essere in conflitto fra loro.

Come fare per risolvere definitivamente la questione? Se sviluppate con Instant Developer vi propongo di usare il DocID: un GUID compresso in 20 caratteri utilizzato per identificare univocamente ogni entità, che risolve in maniera definitiva il problema della crisi d’identità. Se ne volete sapere di più potete leggere il manuale di Instant Developer alle pagine 39 e 229-230. Tra l’altro, usando i DocID non c’è nemmeno bisogno di rileggere il valore della chiave primaria che è già disponibile nella parte client della vostra applicazione.

Mai più crisi d’identità!

Riferimenti:

{ 2 comments… read them below or add one }

1 Teo 7 maggio 2013 alle 16:54

A quando la compatibilita’ con SQLServer 2012 ?

2 Luca Baldini 8 maggio 2013 alle 10:30

@Teo La compatibilità con SQL Server 2012 è prevista in una delle prossime versioni di Instant Developer. Io sono a conoscenza di un solo problema legato a quella versione del database dovuto ad una breaking change di Microsoft riguardo la sintassi della definizione dei trigger. Se non ho capito male il problema si risolve impostando la compatibilità con SQL Server 2008 ma non ho analizzato il problema in dettaglio.

Se sei a conoscenza di altri problemi di compatibilità contattaci così ne veniamo a conoscenza anche noi.

Un’ultima cosa: in Prime Radiant c’è un’apposita attività che riguarda il supporto di SQL Server 2012. Ti suggerisco di votarla quando puoi così si sposta in alto nell’elenco.

Leave a Comment

Previous post:

Next post: