2011-05-25 12 views
11

¿Cómo puedo detectar una excepción específica usando C#?
En mi base de datos hay un índice único en algunas columnas.
al usuario inserta registro duplicado esta excepción ha sido tiro:Capturando la excepción específica

No se puede insertar una fila de clave duplicada en el objeto 'dbo. BillIdentity 'con el único índice' IX _BillIdentity '. La declaración ha finalizado.

¿Cómo puedo detectar esta excepción?
Actualmente estoy comprobando que utiliza este código:

catch (Exception ex) { 
    if (ex.Message.Contains("Cannot insert duplicate key row in object 'dbo._BillIdentity' with unique index 'IX__BillIdentity")) { 
     string ScriptKey = "$(function() {ShowMessage('Error');});"; 
     ScriptManager.RegisterStartupScript(Page, GetType(), "script", ScriptKey, true); 
    } 
} 

creo que su código malo olor.
¿Hay alguna manera mejor?

+1

¿Por qué no comprueba si la clave existe antes de intentar ejecutar la instrucción de inserción? –

+0

@Johann Blais, ¿Cuáles son los beneficios de este trabajo? – Shahin

+2

Evitar la solución alternativa basada en excepciones que está pidiendo;) –

Respuesta

9

No ha mostrado el tipo de excepción que se lanza, pero puede detectar ese tipo de excepción específica. Por ejemplo:

catch (DuplicateKeyException e) { 
    ... 
} 

Es posible que no habrá un tipo de excepción específica para simplemente este error - pero si usted tiene que coger algo bastante general como SqlException a continuación, puede buscar más detalles dentro de la clase sí mismo. Por ejemplo, en SqlException hay una propiedad Errors donde puede ver información más detallada sobre cada uno de los (posiblemente múltiples) errores en el lado de la base de datos. Cada SqlError tiene una propiedad Number que dará el tipo de error. Siempre puede recurrir al mensaje si es absolutamente necesario, pero luego debe ser consciente de la posibilidad de que el mensaje cambie para diferentes culturas, etc.

Tenga en cuenta que si usted no está realmente manejo de la excepción, probablemente debería volver a lanzar que:

catch (SqlException e) { 
    if (CheckWeCanHandle(e)) { 
     // Mess with the ScriptManager or whatever 
    } else { 
     throw; 
    } 
} 
+0

gracias, estoy manejando este error En la capa de presentación, no puedo Retirar la excepción. ¿Dónde estoy equivocado? – Shahin

+1

@Shaah, si no puede volver a lanzar, ¿por qué preguntar acerca de _catching_ una exc específica? Parece que quieres manipularlo de manera diferente. –

+1

@shaahin: Probablemente * debería * volver a lanzar cualquier error que no pueda manejar, y luego tener un error consolidado manejando parte de la capa de presentación para dar una página de error apropiada. –

24

Manija SqlException solo en este caso.

[Editar]

Para comprobar excepción clave duplicada en el servidor de MS SQL:

try 
{ 
    // try to insert 
} 
catch (SqlException exception) 
{ 
    if (exception.Number == 2601) // Cannot insert duplicate key row in object error 
    { 
     // handle duplicate key error 
     return;     
    } 
    else 
     throw; // throw exception if this exception is unexpected 
} 

edición: 2601 Cuando viene?

select * 
from sys.messages 
where text like 'Cannot insert duplicate key%' 

Devuelve:

message_id language_id severity is_event_logged text 
----------- ----------- -------- --------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
2601  1033  14  0    Cannot insert duplicate key row in object '%.*ls' with unique index '%.*ls'. The duplicate key value is %ls. 

Uso exception.Number y que hacen referencia a sys.messages vista se puede manejar cualquier excepción específica MS SQL.

+0

hola, Alex, gran respuesta. Exactamente lo que estoy buscando Excepto que es para una excepción diferente. ¿Las referencias sobre estos números de excepción son? –

+1

@LuukKrijnen - puede consultar 'sys.messages' para esos códigos de error. –

+0

@AlexAza ¿Pude detectar de esta manera en qué violación de columna ocurrió? ... Puedo tener más claves únicas en una tabla y quiero capturar cada una de ellas por separado – Learner

0

Sólo se podía coger el SqlException para empezar

catch (SqlException ex) { 
    if (ex.Message.Contains("Cannot insert duplicate key row in object 'dbo._BillIdentity' with unique index 'IX__BillIdentity")) { 
     string ScriptKey = "$(function() {ShowMessage('Error');});"; 
     ScriptManager.RegisterStartupScript(Page, GetType(), "script", ScriptKey, true); 
    } 
} 
1

acabo Recogió un proyecto en el que alguien realizó esta ruta:

Catch ex As SqlException 
    Select Case ex.Number 
      Case 2601 
       ... 

Tenga en cuenta lo siguiente (de sys.messages en SQL Server):

2601 - No se puede insertar una fila de clave duplicada en el objeto '%. * Ls' con el índice único '%. * Ls'.

Pero, ¿qué tal esto?

2627 - Violación de% ls restricción '%. * Ls'. No se puede insertar clave duplicada en el objeto '%. * ls'."

Me acabo de pasar algún tiempo buscando exactamente este problema.

¿Y si cambiamos proveedor de DB? Es de suponer que 2601 no es absolutamente universal ... esto apesta, la OMI. Y si usted es (se) tratando con esto en su capa de presentación, creo que hay cuestiones más importantes que hacer.

Si esto debe ser el mecanismo de elección, enterrar en lo más profundo, en el fondo en el DAL y permite que una Excepción personalizada se filtre. De esta forma, los cambios en el almacén de datos (o, idealmente, este mecanismo) tienen un área de efectos mucho más limitada y usted puede manejar el caso consis cariñosamente sin ninguna pregunta en la capa de presentación.

Actualmente me estoy inclinando por hacer un SELECCIONAMIENTO liviano para una identificación en una conexión abierta y evitar la excepción por completo.

+0

Bien pensado por respuesta. Me gusta. –

Cuestiones relacionadas