17

Uso Entity Framework per accedere ai miei dati SQL. Ho alcuni vincoli nello schema del database e mi chiedo come gestire le eccezioni causate da questi vincoli.Entity Framework: come gestire correttamente le eccezioni che si verificano a causa di vincoli SQL

Ad esempio, ottengo la seguente eccezione in un caso in cui due utenti tentano di aggiungere contemporaneamente un'entità (quasi) identica al DB.

System.Data.UpdateException 
"An error occurred while updating the entries. See the InnerException for details." 

(inner exception) System.Data.SqlClient.SqlException 
"Violation of UNIQUE KEY constraint 'Unique_GiftId'. Cannot insert duplicate key in object 'dbo.Donations'.\r\nThe statement has been terminated." 

Come rilevare correttamente questa specifica eccezione?

soluzione sporca:

catch (UpdateException ex) 
    { 
     SqlException innerException = ex.InnerException as SqlException; 
     if (innerException != null && innerException.Message.StartsWith("Violation of UNIQUE KEY constraint 'Unique_GiftId'")) 
     { 
      // handle exception here.. 
     } 
     else 
     { 
      throw; 
     } 
    } 

Ora, mentre questo approccio funziona, ha alcuni aspetti negativi:

  • No Tipo di sicurezza: il codice dipende il messaggio di eccezione che contiene il nome del colonna unica.
  • Dipendenza sulle classi SqlClient (astrazione rotto)

Sai una soluzione migliore per questo? Grazie per tutti i feedback ..

Nota: Non voglio codificare i vincoli manualmente all'interno del livello di applicazione, voglio avere loro nel DB.

risposta

17

si dovrebbe essere in grado di intrappolare il numero degli errori di SQL (che è SqlException.Number)

In questo caso si tratta di 2627 che è stato lo stesso per sempre per SQL Server.

Se si desidera l'astrazione, si avrà sempre una certa dipendenza dal motore del database poiché ognuno genererà numeri e messaggi di eccezione diversi.

+0

Va bene, ma anche se io uso questo ID, devo analizzare il messaggio di eccezione per il nome della colonna. – driAn

+0

@driAn: corretto. SQL non ha nemmeno un meccanismo nativo per il drill su quale vincolo o colonna, il che significa che non ci sono API o simili da leggere. – gbn

2

Un modo è di ispezionare lo Errors property dell'interno SqlException. La classe SqlError ha un Number property che identifica l'errore esatto. Consultare la tabella master.dbo.sysmessages per un elenco di tutti i codici di errore.

Naturalmente questo ti lega ancora al server Sql. Non sono a conoscenza di un modo per astrarre questo a parte il semplice "analizzatore di eccezioni EF".

0

Questo scenario non dovrebbe accadere in quanto la chiave non dovrebbe mai essere assegnata esplicitamente quando si utilizza EF; piuttosto permettendo al contesto di assegnarne uno appropriato. Se si tratta di un problema di concorrenza, è necessario eseguire l'aggiornamento nell'ambito di una transazione.

Quindi, se si dispone di un UpdateException, è possibile riprovare l'aggiornamento. È possibile farlo in modo sicuro nell'ambito di una transazione e completare l'ambito solo quando l'aggiornamento è completo. In questo scenario le possibilità che l'aggiornamento passi la prossima volta è maggiore della prima.

Problemi correlati