Jump to content


Photo

Perdida conexion adoconnection


  • Please log in to reply
13 replies to this topic

#1 elrodrix

elrodrix

    Member

  • Miembros
  • PipPip
  • 24 posts

Posted 07 July 2013 - 01:18 PM

Que tal? una consulta sencilla:

Estoy trabajando una aplicacion que usa adoconnection para la conex a la DB (MOTOR MYSQL), y todos los componentes ADO(stored procedure, data source, etc) se conectan al adoconnection.

PREGUNTA: En que evento del adoconnection puedo tirar un mensaje de "ERROR EN LA CONEXION DE LA BASE DE DATOS" por ejemplo, en el caso se corte la conexion al servidor (es una aplicacion que trabaja en una red LAN) ya sea por un bajon de luz, se reinicio el switch/router, sabotearon el cable LAN, etc. No se si estoy en lo correcto de tirar un mensaje en algun evento del adoconnection. Esto me serviria cuando, en vez de que MYSQL me tire mensajes raros cuando se pierde la conexion, DELPHI tire un mensaje diciendo que es error en la conexion de la BD.

Gracias y saludos.
  • 0

#2 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4266 posts
  • LocationCosta Rica

Posted 07 July 2013 - 01:29 PM

Hola
Me parece que se tendria que saber como te conectas a la BD con el doconnection.
Yo usaria un try exce... para generar un mensaje.
Se tendria que saber como te conectas y cuando, me parece.
Saludos
  • 0

#3 elrodrix

elrodrix

    Member

  • Miembros
  • PipPip
  • 24 posts

Posted 07 July 2013 - 01:41 PM

Cuando abro mi aplicacion, hago click en un boton de "CONECTAR" y en ese evento envio la cadena de conexion al ADO y le pongo conected en TRUE. De ahi, el usuario interactua normalmente con el programa ya conectado. En el caso de que por ejemplo de corte el cable LAN o se funda la placa de red, se pierde la conexion a la BD, entonces, MYSQL me tira un error de conexion. Mi idea es poder capturar ese error en algun lado de algun evento de algun componente para que DELPHI envio un mensaje que hay un error de CONEXION.
  • 0

#4 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4266 posts
  • LocationCosta Rica

Posted 07 July 2013 - 01:44 PM

Hola
Hay dos cosas.
1 cuando se esta conectado y se pierde la conexion.
2 cuando se va a conectar y no hay conexion.
me gustaria ver el codigo y ver donde metemos el mensaje.
Pon el codigo aqui.
Saludos
  • 0

#5 elrodrix

elrodrix

    Member

  • Miembros
  • PipPip
  • 24 posts

Posted 07 July 2013 - 01:49 PM

Esto tengo en mi boton "CONECTAR"



delphi
  1. procedure TFMain.ConectaraBD1Click(Sender: TObject);
  2. begin
  3.   with DM1.ADOConnection1 do
  4.     begin
  5.       if Connected then
  6.         begin
  7.           Messagedlg('YA ESTA CONECTADO A BD',mtWarning,[mbok],0);
  8.           Exit
  9.         end;
  10.       try
  11.         //envio cadena de conexion
  12.         DM1.ADOConnection1.ConnectionString:='Provider=MSDASQL.1;Persist Security Info=False;Data Source=db_faltas';
  13.         Connected:=True;
  14.         Messagedlg('EXITO AL CONECTAR A BD',mtConfirmation,[mbok],0);
  15.         //habilito boton inicar sesion
  16.         MMenu.Items[0].Items[1].Enabled:=True;
  17.         Exit
  18.       except
  19.         raise Exception.Create('ERROR AL CONECTAR A BD');
  20.       end;
  21.     end;
  22. end;



En los casos que mencionas, seria el primero, cuando ya estoy conectado (esto es apenas hago click en CONECTAR) y por X motivo se pierde la conexion, en ese caso es MYSQL el que me envia error de conexion (cuando por ejemplo uso un ADOstoredprocedure o un datasource) y no delphi, porque no se en donde tengo que capturar esa perdida de conexion para enviar un mensaje.
  • 0

#6 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4266 posts
  • LocationCosta Rica

Posted 07 July 2013 - 01:56 PM

Hola
Me extraña un poco el primer mensaje pero bueno....
Lo que podrias hacer es crear un procedimiento adicional y llamarlo cuando se necesite comprobar, algo asi:



delphi
  1. Procedure conectado;
  2. begin
  3.   if DM1.ADOConnection1.Connected = true then
  4.   //
  5.   else
  6.   Showmessage('la BD perdio la conexion');
  7. end;



Saludos
  • 0

#7 elrodrix

elrodrix

    Member

  • Miembros
  • PipPip
  • 24 posts

Posted 07 July 2013 - 02:13 PM

Gracias por la sugerencia. El tema de tu codigo es que: no se trata de comprobar en un momento exacto si hay conexion o no, sino de que, cada vez que se use un componente que se encuentre vinculado al ADO connection (un adostoredprocedure por ejemplo), DELPHI tire un mensaje de error en el caso de ADO CONNECTION pierda la conexion por algun motivo.

Por ejemplo: Inicio mi programa, conecto, me logueo como usuario, interacturo con la BD. En un momento apago el servidor. y sale este mensaje cuando hago una consulta por ejemplo

Posted Image

Ese mensaje de MYSQL quiero capturar en delphi para que DELPHI me tire un mensaje de ERROR EN LA CONEXION.
  • 0

#8 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4266 posts
  • LocationCosta Rica

Posted 07 July 2013 - 02:21 PM

Hola
No entiendo bien.
En esencia todos los componentes se enlazan al adoconnection, si este (que es el que tiene la conexion) la pierde ningun componente funcionara.
La idea de un procedimiento es que se verifique antes de que se ejecute alguna operacion.
Otra forma es una comprobacion constante de la conexion con un timer, asi si se pierde no se tendra que esperar a que se haga nada, se generara un mensage de falta de conexión.
saludos
  • 0

#9 elrodrix

elrodrix

    Member

  • Miembros
  • PipPip
  • 24 posts

Posted 07 July 2013 - 02:37 PM

Claro, tenes razon, si adoconnection pierde la conexion, ningun componente funcionara, eso se entendio perfectamente. Yo quiero saber si se puede capturar en un mensaje esa perdida de conexion para mandarle al usuario.

Tienes toda la razon en el caso de un procedimiento, pero si tengo mil componentes ADOstoredprocedure enlazados en el adoconnection, seria una perdida de tiempo comprobar en cada uno si hay conexion antes de realizar una operacion.

Creo suponer que antes de comprobar en cada componente si el ADO tiene conexion, se podria codificar en algun evento del ADOCONNECTION si hay conexion o no antes de que otro componente (adostoredprocedure) solicite su intervencion.

Lei lo del timer, como seria ?
  • 0

#10 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4266 posts
  • LocationCosta Rica

Posted 07 July 2013 - 02:41 PM

Hola
En el evento AfterConect del adoConnection (cuando ya esta conectado) se establece un llamado al timer el que esta comprobando cada X tiempo si se perdio la conexion.
Asi no se necesita saber en cada componente si hay o no hay conexion, el adoconnection lo dira por medio del timer.
Saludos
  • 0

#11 elrodrix

elrodrix

    Member

  • Miembros
  • PipPip
  • 24 posts

Posted 08 July 2013 - 04:08 AM

gracias nuevamente por tu sugerencia! .. voy a seguir investigando haber si puedo resolver el problema. Saludos
  • 0

#12 elrodrix

elrodrix

    Member

  • Miembros
  • PipPip
  • 24 posts

Posted 08 July 2013 - 12:11 PM

Listo, pude solucionar este pequeño problema, agregando un TApplicationEvents en el Form Principal y con el siguiente codigo en el evento On Exception

[DELPHI]//procedimiento para capturar las fallas en la perdida de conexion de la base de datos
//agregar ComObj en uses del FORM
procedure TFMain.ApplicationEvents1Exception(Sender: TObject; E: Exception);
var
  EO:EOLEException;
begin
  if E is EOLEException then
  begin
    EO:=EOLEException(E);
    if EO.ErrorCode = -2147467259 then
      //error de conexion (disconnected)
      begin
        try
          try
            DM1.ADOConnection1.Close;
          except;
          end;
          DM1.ADOConnection1.Open;
          ShowMessage('FALLA EN LA CONEXION A LA BASE DE DATOS - Reestableciendo, vuelva a intentar!');
        except
          on E:Exception do
            ShowMessageFmt('FALLA EN LA CONEXION A LA BASE DE DATOS!.  '
            + 'Por favor, intente luego!.'#13'Error message: %s', [E.Message]);
          end;
      end
      else
        ShowMessage(E.Message + ' ' + IntToStr(EO.ErrorCode));
    end
  else
    ShowMessage(E.ClassName + #13 + E.Message);
end;[/DELPHI]

Espero que les sirva. Gracias y Saludos
  • 0

#13 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2137 posts

Posted 08 July 2013 - 05:03 PM

Pueda ser que ese código te funcione, pero ese enfoque personalmente lo considero incorrecto, puesto que el uso de  TApplicationEvents tiene un enfoque más general (global) de manejar cualquier excepción que genere la aplicación, por lo tanto sería una locura intentar manejar todas las posibles excepciones desde ese evento; pienso que TApplicationEvents es más útil para personalizar mensajes de error, que para decirle a la aplicación que hacer en cada excepción.

Los mensajes de error podrías agregarlos en un  archivo de texto,  en cada línea algo así: E.message=Mensaje que quiero mostrar.

En el siguiente ejemplo te indico cómo hacerlo, solo hay que colocar el archivo en la misma carpeta del ejecutable.



delphi
  1. type
  2.   TForm1 = class(TForm)
  3.     ApplicationEvents1: TApplicationEvents;
  4.     procedure ApplicationEvents1Exception(Sender: TObject; E: Exception);
  5.   private
  6.     FErrores: TStringList;
  7.   public
  8.     { Public declarations }
  9.   end;
  10.  
  11. var
  12.   Form1: TForm1;
  13.  
  14. implementation
  15.  
  16. {$R *.dfm}
  17.  
  18. procedure TForm1.ApplicationEvents1Exception(Sender: TObject; E: Exception);
  19. const
  20.   SErrorMsgFile = 'mensajes.txt';
  21. var
  22.   I: Integer;
  23.   S, N: string;
  24. begin
  25.   if not Assigned(FErrores) then
  26.   begin
  27.     FErrores := TStringList.Create;
  28.     S := ExtractFilePath(GetModuleName(HInstance)) + SErrorMsgFile;
  29.     if FileExists(S) then
  30.       FErrores.LoadFromFile(S);
  31.   end;
  32.   S := E.Message;
  33.   for I := 0 to FErrores.Count - 1 do
  34.   begin
  35.     N := FErrores.Names[I];
  36.     if Pos(N, S) <> 0 then
  37.     begin
  38.       S := FErrores.Values[N];
  39.       Break;
  40.     end;
  41.   end;
  42.   MessageDlg(S, mtError, [mbOk], 0);
  43. end;



Ahora, lo correcto en tu caso sería que en cada procedimiento que involucre una conexión remota, lo manejes con los bloque try - except - end (como ya te lo han sugerido algunos compañeros), para decirle a tu aplicación como responda en cada caso, independientemente de los mensajes de error, puesto que de esto se encarga el procedimiento anterior. Si no necesitas que haga algo  especial al perder la conexión, con el procedimiento  anterior es suficiente, sin necesidad del bloque try  - except - end.

Saludos.
  • 0

#14 elrodrix

elrodrix

    Member

  • Miembros
  • PipPip
  • 24 posts

Posted 12 July 2013 - 08:40 AM

Pueda ser que ese código te funcione, pero ese enfoque personalmente lo considero incorrecto, puesto que el uso de  TApplicationEvents tiene un enfoque más general (global) de manejar cualquier excepción que genere la aplicación, por lo tanto sería una locura intentar manejar todas las posibles excepciones desde ese evento; pienso que TApplicationEvents es más útil para personalizar mensajes de error, que para decirle a la aplicación que hacer en cada excepción.

Los mensajes de error podrías agregarlos en un  archivo de texto,  en cada línea algo así: E.message=Mensaje que quiero mostrar.

En el siguiente ejemplo te indico cómo hacerlo, solo hay que colocar el archivo en la misma carpeta del ejecutable.



delphi
  1. type
  2.   TForm1 = class(TForm)
  3.     ApplicationEvents1: TApplicationEvents;
  4.     procedure ApplicationEvents1Exception(Sender: TObject; E: Exception);
  5.   private
  6.     FErrores: TStringList;
  7.   public
  8.     { Public declarations }
  9.   end;
  10.  
  11. var
  12.   Form1: TForm1;
  13.  
  14. implementation
  15.  
  16. {$R *.dfm}
  17.  
  18. procedure TForm1.ApplicationEvents1Exception(Sender: TObject; E: Exception);
  19. const
  20.   SErrorMsgFile = 'mensajes.txt';
  21. var
  22.   I: Integer;
  23.   S, N: string;
  24. begin
  25.   if not Assigned(FErrores) then
  26.   begin
  27.     FErrores := TStringList.Create;
  28.     S := ExtractFilePath(GetModuleName(HInstance)) + SErrorMsgFile;
  29.     if FileExists(S) then
  30.       FErrores.LoadFromFile(S);
  31.   end;
  32.   S := E.Message;
  33.   for I := 0 to FErrores.Count - 1 do
  34.   begin
  35.     N := FErrores.Names[I];
  36.     if Pos(N, S) <> 0 then
  37.     begin
  38.       S := FErrores.Values[N];
  39.       Break;
  40.     end;
  41.   end;
  42.   MessageDlg(S, mtError, [mbOk], 0);
  43. end;



Ahora, lo correcto en tu caso sería que en cada procedimiento que involucre una conexión remota, lo manejes con los bloque try - except - end (como ya te lo han sugerido algunos compañeros), para decirle a tu aplicación como responda en cada caso, independientemente de los mensajes de error, puesto que de esto se encarga el procedimiento anterior. Si no necesitas que haga algo  especial al perder la conexión, con el procedimiento  anterior es suficiente, sin necesidad del bloque try  - except - end.

Saludos.


Gracias por tu respuesta. Solo que te corrigo el "puede ser que funcione" a "el codigo funciona perfectamente". En cuanto al enfoque personal que mecionas, me parece correcto. En mi caso, mi cliente solo queria que personalice los errores de la aplicacion, que con un par de lineas logre lo que me pedia, cosa que lo de enfoque y esas cosas jamas me hablo mi cliente.

Seguro despues voy a probar tu codigo y despues colgare los resultados. Saludos
  • 0




IP.Board spam blocked by CleanTalk.