Ultimo Id errato usando SCOPE_IDENTITY()

di il
6 risposte

Ultimo Id errato usando SCOPE_IDENTITY()

Gentili,
un cliente che usa il ns. gestionale basato su SqlServer riferisce di un'anomalia che occorre non più di 2-3 volte l'anno su un totale di 2-3000 movimenti, ma ogni anno, quando inserisce dei movimenti di magazzino.
Per inserire i movimenti di magazzino usiamo due stored procedure, una per l'inserimento della testata del movimento che ritorna l'Id e una a cui passiamo l'Id testata per generare le righe dello stesso.
Nella testata ci sono queste righe:

INSERT INTO dbo.magazzino (......) VALUES ()
SET @Id = SCOPE_IDENTITY();
Niente di nuovo.
Il problema è che sporadicamente l'id ritornato dallo SCOPE_IDENTITY() non è quello corretto, in quanto ritorna l'id di un altro movimento agganciando quindi tutte le righe di questa testata a quelle dell'altro movimento.
E' possibile un'evenienza del genere nel caso in cui più utenti salvino dei movimenti "nello stesso momento"? Ho cercato in Internet ma non ho trovato nulla di soddisfacente.
Secondo voi posso migliorare la situazione usando una transaction, es.

BEGIN TRANSACTION
	BEGIN TRY
	INSERT INTO dbo.magazzino (......) VALUES ()
	SET @Id = SCOPE_IDENTITY();
	COMMIT TRANSACTION
END TRY
....
Ringrazio chiunque vorrà darmi una dritta o qualche link di approfondimento.
Buon weekend.
Lucius

6 Risposte

  • Re: Ultimo Id errato usando SCOPE_IDENTITY()

    Non uso SQL Server ma MariaDB/MySQL quindi posso solo cercare di fare un paragone (ma per logica credo che sia applicabile anche a SQL SERVER).

    L'IDENTITY affinché abbia un senso deve essere relativo alla connessione quindi più connessioni (utenti) che dovessero effettuare insert concorrenti dovrebbero (devono) ottenere ID differenti, a maggior ragione se vengono utilizzate le transazioni. Ribadisco che questo comportamento l'ho verificato con MariaDB/MySQL (e non vedo perché SQL SERVER debba agire in maniera diversa).
  • Re: Ultimo Id errato usando SCOPE_IDENTITY()

    Prova anche a guardare la clausola OUTPUT.

    Io l'ho usata con successo in un'applicazione in C#, strutturando opportunamente l'INSERT, ma credo possa fare al caso tuo.
  • Re: Ultimo Id errato usando SCOPE_IDENTITY()

    Ti confermo che è corretto che sia stato usato SCOPE_IDENTITY().
    Sicuro che il problema non risiede altrove? magari da qualche parte nel programma viene eseguita una query farlocca.
  • Re: Ultimo Id errato usando SCOPE_IDENTITY()

    Salve,
    se il codice di @Lucius e' "veramente"
    
    INSERT INTO dbo.magazzino (......) VALUES ()
    SET @Id = SCOPE_IDENTITY();
    quindi SCOPE_IDENTITY() e' letto immediatamente dopo l'esecuzione dell'insert, quindi effettivamente nello stesso scope, e ritornato per l'utilizzo in altro command, allora dovrebbe essere corretto... non e' necessario in questo senso il supporto transazionale, al di la' del fatto che un master detail a mio parere vada sempre gestito in maniera atomica e quindi in unica transazione

    sono a conoscenza di anomalie/problematiche dove SCOPE_IDENTITY() ritorna NULL, ma non di anomalie di questo genere come da @Lucius riportato

    @Toki ha probabilmente ragione...

    salutoni romagnoli
  • Re: Ultimo Id errato usando SCOPE_IDENTITY()

    Gentili,
    intanto vi ringrazio per le risposte come sempre puntuali ed approfondite.
    Confermo quello che ho scritto e le puntualizzazioni fattemi nelle risposte.
    1) L'Id ritornato ha la clausola OUTPUT;
    2) SCOPE_IDENTITY() è richiamato subito dopo l'INSERT INTO (in mezzo ci sono soltanto una riga vuota e una riga di commento con i --).
    Siccome il cliente non ci ha ancora fornito il db di produzione, nel weekend ho fatto delle prove con un db identico a livello di struttura:
    1) con SSMS aprendo più tab all'interno dello stesso management studio e lanciando la query SCOPE_IDENTITY() funziona correttamente;
    2) da .Net con EF 6.4 lanciavo 20!!! thread contemporanei che mi inserivano la riga di intestazione e 20 righe di dettaglio per ciascuna intestazione e non ho notato nessun "accavallamento", ed il tutto ci impiegherà un paio di secondi max in tutto.
    Vi ringrazio ancora per la Vs. disponibilità e competenza.
    Lucius.
  • Re: Ultimo Id errato usando SCOPE_IDENTITY()

    Gentili,
    ritorno sull'argomento per aggiornarvi sulle ultime news.
    Dopo aver insistito per avere il db reale di produzione del cliente, e aver controllato tutti i movimenti che secondo il cliente erano errati, abbiamo verificato che non c'è nessun bug nell'uso dello SCOPE_IDENTITY(), l'Id tornato dopo l'inserimento della testata è assolutamente corretto e non c'è nessun errore di attribuzione dell'Id nell'inserimento delle righe sottostanti.
    Quello che ha tratto in inganno il cliente è un errore della descrizione del movimento, NON dipendente dalla query perché viene passata dalla maschera del gestionale, che sia per i movimenti di carico che per quelli di scarico riporta la descrizione "Scarico per prod" ma gli Id sono esatti; non c'è nessun Id ritornato errato.
    Vi ringrazio ancora per le info, come sempre utili e precise.
    Lucius
Devi accedere o registrarti per scrivere nel forum
6 risposte