Como mantener el mensaje de error en try catch anidados.

529 views
Skip to first unread message

mpulla

unread,
Mar 14, 2013, 12:53:11 PM3/14/13
to publice...@googlegroups.com

Buen día Foxeros.

Tengo el siguiente código (resumido), el cual corre bien, pero cuando intentó ingresar un código duplicado en el método CntPersona.Personaupdateprocess() que esta anidado dentro del Try Catch la db devuelve el mensaje de error y lo retorno con THROW loException este va al método RecorsSave y este a su vez a método Grabar_proceso, donde proceso el mensaje de error para mostrarlo al usuario y en lugar de mostrarme 'No se puede insertar una fila de clave duplicada en el objeto 'App.Persona' con índice único 'IX_Persona_cSRIId'. El valor de la clave duplicada es (0123136522).', me muestra el mensaje de la imagen adjunta, que no tiene nada que ver con el error.

Si no estoy mal hace algún tiempo alguien expuso la forma de conservar el mensaje de error en try catch anidados si tienen el link o si me pueden ayudar con alguna idea se los agradezco

Trabajo con VFP 9 SP 2 Con Sql Server

Saludos.
Mauricio

Metodo Grabar_proceso
WITH ThisForm
    LOCAL lcErrMsg  As String, llError AS Logical, loException As Exception
    TRY   
            IF .RecordSave()
                IF .lAddMode
                    .RecordSaveAddSeveralAfter()
                ELSE
                    .RecordSaveEditSeveralAfter()
                ENDIF
            ENDIF
    CATCH TO loException
        lcErrMsg = ThisForm.ErrorProcess(loException)
    FINALLY
  
    ENDTRY
   
    IF !EMPTY(lcErrMsg)
        MESSAGEBOX(lcErrMsg, 64, ERRORTITLE_LOC)
        RETURN .F.
    ENDIF
ENDWITH

Metodo RecorsSave
LOCAL loException As Exception, lcErrMsg As String, lcSql As String
PRIVATE liUsuarioId As Integer, lcDBCAuditoriaTipo As String, liPersonaId As String, liPacienteId As Integer, liHCId  As Integer, liTransactions As Integer
       
liUsuarioId    = _Screen.oUser.iUserid

SELECT PacienteRs
TRY
    WITH This
        DO CASE
            CASE .lAddMode AND .lEditMode    &&ADD
                IF .CntPersona.oPersonadata.iPersonaId = 0
                    liPersonaId = .CnTPERSONA.Personainsert()
                ELSE
                    liPersonaId = .cnTPERSONA.oPersonadata.iPersonaId
                    .CntPersona.Personaupdateprocess()
                ENDIF
               
            CASE !.lAddMode AND .lEditMode         &&Edit
                .CntPersona.Personaupdateprocess()
               
        ENDCASE
    ENDWITH
CATCH TO loException
    THROW loException
FINALLY

ENDTRY

Proceso .CntPersona.Personaupdateprocess()
LOCAL loException As Exception

TRY
    IF SQLEXEC(_Screen.odBCTALK.iodbchandle, lcSql, 'AnswerRs') < 0
        AERROR(laError)
        Error laError(2)
    ELSE
        lcSql = [App.DBAuditoria_spI ?liDBAudId, ?liUsuarioId, ?lcTipo, ?lcCambio, ?@liKey]
        IF SQLEXEC(_Screen.odBCTALK.iodbchandle, lcSql) < 0
            AERROR(laError)
            Error laError(2)
        ENDIF        
    ENDIF   
CATCH TO loException
    THROW loException
ENDTRY

Mensaje de Error.png

Pablo Daniel Lissa

unread,
Mar 14, 2013, 2:10:25 PM3/14/13
to publice...@googlegroups.com
Mauricio:

Hola. Cada vez que lanzas una excepción de forma explícita (con THROW), el objeto Exception que instancia VFP tiene como propiedad el código de error 2071 y el mensaje "User thrown error" (Error iniciado por el usuario).

Lo que se haya puesto luego del comando THROW va a parar a la propiedad UserValue del objeto Exception. Así, en tu caso, es esa propiedad debes tener el objeto loException que relanzaste en el bloque CATCH.

Saludos.

Fernando D. Bozzo

unread,
Mar 14, 2013, 6:34:47 PM3/14/13
to publice...@googlegroups.com

Hola Mauricio, la solución es relanzar el error solo con THROW, no con THROW loException. El agregado de ese parámetro reconvierte el error original en el nuevo, dejando al error original en la propiedad UserValue. Usando solo THROW se relanza el mismo error al nivel superior sin cambios.

Supongo que esto es porque FoxPro no tiene forma de saber si alteraste el contenido de loException (que se puede), y entonces asume que si especificás el objeto es porque ya no te interesa el original, aunque en ese caso lo anida en UserValue.


Saludos.-

mpulla

unread,
Mar 14, 2013, 7:06:15 PM3/14/13
to publice...@googlegroups.com

Hola Pablo y Fernando.

Gracias por las respuestas.

Pablo la verda no entendi lo que quieres decir con "Lo que se haya puesto luego del comando THROW va a parar a la propiedad UserValue del objeto Exception. Así, en tu caso, es esa propiedad debes tener el objeto loException que relanzaste en el bloque CATCH"
Antes de escribir probe así en el try catch más anidado pero no dio resultado
loException.UserValue = loException
THROW loException

Ahora como me dijo Fernando relance el error solo con THROW y tuve lo que quería.

Gracias por la ayuda
Mauricio

Pablo Daniel Lissa

unread,
Mar 14, 2013, 11:43:31 PM3/14/13
to publice...@googlegroups.com
Respecto a lo que quise decir anteriormente, primero marco que me equivoqué en una letra que deja sin sentido a toda la oración. Donde dice:

    Así, en tu caso, es esa propiedad debes tener el objeto loException que relanzaste en el bloque CATCH
debe decir:
    Así, en tu caso, "en" esa propiedad debes tener el objeto loException que relanzaste en el bloque CATCH

Habiendo corregido eso, pongo un ejemplo para aclarar lo que quería expresar:
TRY
    TRY
        a = "a" / 0
    CATCH TO loErrorDivisionIncorrecta
        THROW loErrorDivisionIncorrecta
    ENDTRY
CATCH TO loError
    loExcAnidada = loError.UserValue
    MESSAGEBOX(loExcAnidada.Message)
ENDTRY


En este caso, se relanza explícitamente la excepción loErrorDivisionIncorrecta, pero, la excepción capturada (loError) ya no es la misma, sino que es una excepción de tipo 2071 (Excepción iniciada por el usuario) y que contiene anidada en la propiedad UserValue la excepción original. Luego, "lo que se puso luego de THROW" (loErrorDivisionIncorrecta) "fue a parar a la propiedad UserValue" (de loError). Espero haberme explicado mejor.

Igual, escribo esto solamente para no dejar inconclusa la pregunta, ya que la propuesta de Fernando es mucho más práctica y sencilla. La verdad, yo pensaba que era lo mismo THROW y THROW loException. Así que este tema me sirvió a mí también para aclarar ese tema.

Gracias. Saludos.

mpulla

unread,
Mar 15, 2013, 10:56:30 AM3/15/13
to publice...@googlegroups.com

Hola Pablo.

Gracias por la aclaración.

Saludos.
Mauricio
Reply all
Reply to author
Forward
0 new messages