17

Utilizo Entity Framework para acceder a mis datos SQL. Tengo algunas limitaciones en el esquema de la base de datos y me pregunto cómo manejar las excepciones que son causadas por estas restricciones.Entity Framework: cómo manejar adecuadamente las excepciones que se producen debido a restricciones de SQL

Como ejemplo, aparece la siguiente excepción en un caso en el que dos usuarios intentan agregar una entidad (casi) idéntica a la base de datos al mismo tiempo.

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." 

¿Cómo puedo detectar adecuadamente esta excepción específica?

solución sucia:

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; 
     } 
    } 

Ahora bien, aunque este enfoque funciona, tiene algunos inconvenientes:

  • Sin la seguridad de tipos: El código depende del mensaje de excepción que contiene el nombre de la columna única
  • La dependencia de las clases SQLClient (abstracción roto)

¿Conoce una mejor solución para esto? Gracias por todos los comentarios ..

Nota: no quiero que codificar manualmente las limitaciones dentro de la capa de aplicación, quiero tener en la base de datos.

Respuesta

17

usted debería ser capaz de atrapar el número de errores de SQL (que es SqlException.Number)

En este caso se trata de 2627, que ha sido siempre la misma para SQL Server.

Si desea la abstracción, siempre tendrá alguna dependencia en el motor de la base de datos porque cada uno arrojará diferentes números de excepción y mensajes.

+0

Bien, pero incluso si uso esta identificación, tengo que analizar el mensaje de excepción para el nombre de la columna. – driAn

+0

@driAn: correcto. SQL tampoco tiene un mecanismo nativo para explorar a qué restricción o columna, lo que significa que tampoco hay una API o tal para leerlo. – gbn

2

Una forma es inspeccionar el Errors property de la SqlException interna. La clase SqlError tiene un Number property que identifica el error exacto. Consulte la tabla master.dbo.sysmessages para obtener una lista de todos los códigos de error.

Por supuesto, esto todavía lo vincula al Servidor SQL. No tengo conocimiento de una forma de abstraer esto, aparte de rodar tu propio 'analizador de excepciones EF'.

0

Este escenario no debería ocurrir ya que la clave nunca debería asignarse explícitamente cuando se usa EF; más bien permitiendo que el contexto asigne uno apropiado. Si es un problema de simultaneidad, entonces debe hacer la actualización en un alcance de transacción.

Luego, si tiene una UpdateException, puede volver a intentar la actualización. Puede hacerlo de forma segura en un ámbito de transacción y solo completar el alcance cuando la actualización sea exhaustiva. En este escenario, las posibilidades de que la actualización continúe la próxima vez es mayor que la primera.

Cuestiones relacionadas