Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 08-03-2010
andressanchez andressanchez is offline
Miembro
 
Registrado: jul 2005
Ubicación: Sando Domingo, Rep. Dom.
Posts: 109
Poder: 19
andressanchez Va por buen camino
Manejo de excepciones de base de datos

Buenas tardes foristas

Estoy usando delphi 7, componentes ADO y como gestor de base de datos MS SQL Server 2000.

Tengo el siguiente problema, necesito capturar una excepcion del tipo EOleException y EDatabaseError y determinar que tipo de excepcion es para el manejador de la base de datos, es decir, si es por ejemplo una excepcion del tipo "violetion unique key" capturar la excepcion y mostrarle al usuario un mensaje personalizado y que lo entienda.

He buscado en el foro y lo que e encontrado no satisfe mi problema.

Otra cosa que e visto es que cuando me envia una excepcion del manejador de la base de datos me muestra tres excepciones seguidas de diferentes tipos cuando dispara la excepcion en mi entorno de desarrollo y son EoleExeption, eDatabaseError y EAccessViolation, y la ultima es la que toma en cuenta. Les adjunto el código que utilizo a ver si pueden ayudarme.

Código:
procedure TFrmMantPresenciaTecnica.btnGenerarObjetivosClick(Sender: TObject);
var
  InputString, Compania, Distrito, Supervisor, sMensaje: string;
  FechaInicial, FechaFinal: TDatetime;
  Proceso, CantidadEsperada: integer;
begin
try
   InputString:= InputBox('Digite la fecha', 'El proceso empezará a generar a partir del ' +
         DateToStr(qryPresenciaTecnicaFECHA.Value) + ' Hasta la fecha que usted digite a continuacion.', '');
   FechaInicial := qryPresenciaTecnicaFECHA.Value;
   FechaFinal := StrToDate(inputString);
sMensaje := 'Esta seguro que desea generar desde el ' + DateTostr(FechaInicial) + ' hasta el ' + DateTostr(FechaFinal) + '.';
if MessageDlg(sMensaje,
    mtConfirmation, [mbYes, mbNo], 0) = mrNo then
  begin
   ShowMessage('Operación cancelada por el usuario.');
   Abort;
  end;
 
if (FechaInicial >= FechaFinal) then
 begin
  ShowMessage('La fecha de inicio no puede ser mayor o igual a la fecha final');
  Abort;
 end;
FechaInicial :=  FechaInicial + 1;
qryPresenciaTecnica.DisableControls;
Compania := qryPresenciaTecnicaCODIGO_COMPANIA.Value;
Distrito := qryPresenciaTecnicaCODIGO_DISTRITO.Value;
Supervisor := qryPresenciaTecnicaCODIGO_SUPERVISOR.Value;
Proceso := qryPresenciaTecnicaCODIGO_PRODUCTO.Value;
CantidadEsperada := qryPresenciaTecnicacantidad_esperada.Value;

while FechaInicial <= FechaFinal do
begin
 qryPresenciaTecnica.Append;
 qryPresenciaTecnicaCODIGO_COMPANIA.Value := Compania;
 qryPresenciaTecnicaCODIGO_DISTRITO.Value := Distrito;
 qryPresenciaTecnicaCODIGO_SUPERVISOR.Value := Supervisor;
 qryPresenciaTecnicaCODIGO_PRODUCTO.Value := Proceso;
 qryPresenciaTecnicaFECHA.Value := FechaInicial;
 qryPresenciaTecnicacantidad_esperada.Value := CantidadEsperada;
 qryPresenciaTecnicaESTATUS.Value := 'REGISTRADO';
 qryPresenciaTecnica.Post;

FechaInicial :=  FechaInicial + 1
end;
qryPresenciaTecnica.EnableControls;
Showmessage('Proceso terminado correctamente.') ;
except
  {on e: Exception do
   begin
    Showmessage('Error Digitando la fecha.');
   end;}
  on e: EOleException do
   begin
    showmessage('ole exception')
   end;
  on E: EDatabaseError do
   begin
      showmessage('adoerror');
   end;
  on e: EAccessViolation do
   begin
    showmessage('error violacion de acceso');
   end;
end;
end;

Gracias de antemano,

saludos.-
Responder Con Cita
  #2  
Antiguo 09-03-2010
andressanchez andressanchez is offline
Miembro
 
Registrado: jul 2005
Ubicación: Sando Domingo, Rep. Dom.
Posts: 109
Poder: 19
andressanchez Va por buen camino
Amigos foristas,

Tuve que buscar una solución alterna al manejo de excepciones.

Lo que hice fue una función que me devuelve un valor booleano si existe o no el registro que se intenta insertar y no dejo que la excepción se produzca en el manejador de la base de datos. Lo único malo de esto es que el programa va estar leyendo constantemente a la base de datos y esto le resta velocidad a la aplicación.

Hubiera preferido hacerlo con el manejo de excepciones por ser una solución mas óptima y eficiente.

Saludos.-
Responder Con Cita
  #3  
Antiguo 09-03-2010
Avatar de rgstuamigo
rgstuamigo rgstuamigo is offline
Miembro
 
Registrado: jul 2008
Ubicación: Santa Cruz de la Sierra-Bolivia
Posts: 1.646
Poder: 17
rgstuamigo Va por buen camino
Arrow

El problema que veo con lo que estas haciendo es que no estas separando la logica de negocio con la interfaz de usuario, en otras palabras lo que estas haciendo es programar todo en la unidad del formulario, lo cual te va generar un dolor de cabeza cuando más adelante agregues o modifiques algo en tu aplicación.
Consejo :
Existen formas o estrategias que puedes implementar para que tu aplicacion sea bastante ordenada y bien estructurada como por ejemplo deberías separar tu aplicacion en capas: La capa de acceso a datos, la capa de lógica de negocio, y la capa de interfaz de usuario., de ésta manera cada capa se encarga de su tarea especifica, en caso de querer manejar o personalizar los errores pues puedes hacerlo en la capa de Lógica de Negocio que es donde podrias hacer todas las validaciones y comprobaciones para ver si los datos son los correctos y no estan repetidos..
Para más informacion sobre el manejo de capas desde Delphi puedes ver estas 5 partes(1, 2, 3, 4, 5).En la primera parte se menciona las diferentes capas..
En éste hilo en los post #3 y #4 puedes ver algunas formas de personalizacion de los errores.
Saludos...
__________________
"Pedid, y se os dará; buscad, y hallaréis; llamad, y se os abrirá." Mt.7:7
Responder Con Cita
  #4  
Antiguo 09-03-2010
andressanchez andressanchez is offline
Miembro
 
Registrado: jul 2005
Ubicación: Sando Domingo, Rep. Dom.
Posts: 109
Poder: 19
andressanchez Va por buen camino
Muchas gracias rgstuamigo por tu consejo.

Voy a tener que hacer una propuesta para que me aprueben
este desarrollo en capas y modificar el sistema completo.

A parte de personalizarlo me gustaría saber cómo detectar o saber por ejemplo la excepción del gestor de base de datos "Violation of UNIQUE KEY constraint XXXXX", "Cannot insert the value NULL into column YYYYY" o "INSERT statement conflicted with COLUMN FOREIGN KEY constraint" para cuando se presente mostrarle al usuario lo siguiente:


-"Cannot insert the value NULL into column YYYYY" = No puede insertar nulo en el campo xxx

-"Violation of UNIQUE KEY constraint XXXXX" = Registro duplicado

-"INSERT statement conflicted with COLUMN FOREIGN KEY constraint" = Referencia no existe.

Es decir atendiendo al error que me devuelva el gestor de base de datos mostraré mi mensaje personalizado.

Saludos.-
Responder Con Cita
  #5  
Antiguo 09-03-2010
Avatar de rgstuamigo
rgstuamigo rgstuamigo is offline
Miembro
 
Registrado: jul 2008
Ubicación: Santa Cruz de la Sierra-Bolivia
Posts: 1.646
Poder: 17
rgstuamigo Va por buen camino
Arrow

Segun he visto, se puede capturar el código de error que el Servidor de base de dato emite, talves éste hilo te pueda ayudar en algo aunque creo que dependerá de qué componentes estes usando para conectarte.
En lo personal nunca he necesitado hacer algo por el estilo..
saludos...
__________________
"Pedid, y se os dará; buscad, y hallaréis; llamad, y se os abrirá." Mt.7:7

Última edición por rgstuamigo fecha: 09-03-2010 a las 20:03:25.
Responder Con Cita
  #6  
Antiguo 09-03-2010
andressanchez andressanchez is offline
Miembro
 
Registrado: jul 2005
Ubicación: Sando Domingo, Rep. Dom.
Posts: 109
Poder: 19
andressanchez Va por buen camino
Un millon de gracias voy a probar a ver como me va

les dejo saber.
Responder Con Cita
  #7  
Antiguo 09-03-2010
Avatar de AzidRain
[AzidRain] AzidRain is offline
Miembro Premium
 
Registrado: sep 2005
Ubicación: Córdoba, Veracruz, México
Posts: 2.914
Poder: 21
AzidRain Va camino a la fama
Lo que menciona rgs es muy cierto sin embargo tiene sus bemoles, por ejemplo, tengo una aplicación donde se pueden consultar gran cantidad de listados de facturas de acuerdo con muy diversos criterios según el usuario que necesite consultarlos (un contador quiere saber que facturas no le han llegado físicamente, un jefe de tráfico quiere saber que facturas ya se embarcaron y asi..) obviamente cada uno deseará consultar el contenido de la factura de vez den cuando. Lo má sencillo es crear una clase (TForm) a la cual le pasas el número de factura y te la muestra en pantalla según lo requieras e incluyes adentro la lógica para acceso a datos (vamos, en este caso es una vil consulta) y además, creas un procedimiento en esa misma unidad que te crea una instancia no-modal o modal segun lo pidas de esa ventana.

De esta forma, en cualquier parte de la aplicación que se desee se puede consutar rápidamente ese dato sin tener que reprogramar nada...una de las bellezas de Delphi. Claro está, hay casos en donde hacer esto a diestra y siniestra te produce cosas peores que el GOTO de BASIC. Como dije en otro post, depende mucho de que tan ordenado seas como desarrollador.
__________________
AKA "El animalito" ||Cordobés a mucha honra||
Responder Con Cita
  #8  
Antiguo 09-03-2010
andressanchez andressanchez is offline
Miembro
 
Registrado: jul 2005
Ubicación: Sando Domingo, Rep. Dom.
Posts: 109
Poder: 19
andressanchez Va por buen camino
Hice pruebas con un proyecto nuevo.

Agregué un datamodulo y allí puse un adoconexion y un adoquery.

En el formulario principal agregué un boton y escribí el siguiente codigo para probar:

Código:
procedure TForm1.btnInsertarClick(Sender: TObject);
begin
b.MiQuery.Open;
b.MiQuery.Append;
b.MiQueryCODIGO_COMPANIA.Value := 'cab';
b.MiQueryCODIGO_SUPERVISOR.Value := '92001';
b.MiQueryCODIGO_DISTRITO.Value := '12a';
b.MiQueryFECHA.Value := StrToDate('10/10/2009');
b.MiQueryCODIGO_PRODUCTO.Value := 1;
b.MiQuerycantidad_esperada.Value := 5;
b.MiQueryESTATUS.Value := 'REGISTRADO';
try
  B.MiQuery.Post;
except
 on E:EOleException do
  begin
   showmessage('Mi mensaje de error');
  END;
end;
end;
Este insert lo hice para que dispare una excepción violando un unique key pero no logro capturar la excepción EoleException. Cuando estoy depurando la aplicación delphi me muestra esta excepcion

Cita:
---------------------------
Debugger Exception Notification
---------------------------
Project Project1.exe raised exception class EOleException with message 'Violation of UNIQUE KEY constraint 'UNQ_presencia_tecnica_esperada'. Cannot insert duplicate key in object 'presencia_tecnica_esperada''. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------
Despues que acepto esta ventana me muestra esta otra excepcion:

Cita:
---------------------------
Debugger Exception Notification
---------------------------
Project Project1.exe raised exception class EDatabaseError with message 'Violation of UNIQUE KEY constraint 'UNQ_presencia_tecnica_esperada'. Cannot insert duplicate key in object 'presencia_tecnica_esperada''. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------
A Raiz de esto solamente puedo capturar la excepcion de tipo EDataBaseError y no puedo accesar al codigo de error de la clase EOleException.

Por qué este comportamiento?

Que estoy haciendo mal?

Saludos.-
Responder Con Cita
  #9  
Antiguo 10-03-2010
andressanchez andressanchez is offline
Miembro
 
Registrado: jul 2005
Ubicación: Sando Domingo, Rep. Dom.
Posts: 109
Poder: 19
andressanchez Va por buen camino
Hola amigos,

Hice otra prueba y decidí hacer la sentencia sql del insert y ejecutar el método ExecSQL en vez del Metodo Post. Este es el código:

Cita:
procedure TForm1.btnOtroInsertClick(Sender: TObject);
begin
b.OtroQuery.Close;
b.OtroQuery.SQL.Text := 'INSERT INTO PRESENCIA_TECNICA_ESPERADA ( ' +
' codigo_compania, codigo_supervisor, codigo_distrito, fecha, codigo_producto, ' +
' cantidad_esperada, estatus) values (:com, :sup, :dist, :fech, ro, :esp, :est)';
b.OtroQuery.Parameters.ParamByName('com').Value := 'CAB';
b.OtroQuery.Parameters.ParamByName('sup').Value := '92001';
b.OtroQuery.Parameters.ParamByName('dist').Value := '12a';
b.OtroQuery.Parameters.ParamByName('fech').Value := StrToDate('10/10/2009');
b.OtroQuery.Parameters.ParamByName('pro').Value := 1;
b.OtroQuery.Parameters.ParamByName('esp').Value := 5;
b.OtroQuery.Parameters.ParamByName('est').Value := 'REGISTRADA';
try
B.OtroQuery.ExecSQL;
except
on E:EOleException do
begin

ShowMessage('Mi mensaje de error' + E.Message + ' ' + INTTOSTR(E.ErrorCode));
END;
end;
end;
De esta manera fue que pude capturar el la excepción de la clase EOleException. No se si tiene algo que ver con el Método post el hecho que me dispare dos clases de excepciones diferentes.

Otra cosa que noté fue que utiliza la misma codificación para estas dos excepciones:

//-2147217873 Violation of UNIQUE KEY constraint
//-2147217873 Cannot insert the value NULL into column

Muchas gracias por su ayuda.

Saludos.-
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Manejo de consultas SQL y Base de datos metroyd Conexión con bases de datos 0 07-10-2007 22:31:37
Manejo de Excepciones anghell77 OOP 7 10-08-2006 18:46:48
No me sale el manejo de excepciones Torreblanca Varios 3 11-07-2006 18:32:45
manejo de la base de datos con sql altatrejo Conexión con bases de datos 0 22-08-2005 18:52:04
manejo de excepciones el_barto Varios 4 08-06-2005 09:48:36


La franja horaria es GMT +2. Ahora son las 15:32:25.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi