
Perdida conexion adoconnection
#1
Escrito 07 julio 2013 - 01:18
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.
#2
Escrito 07 julio 2013 - 01:29
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
#3
Escrito 07 julio 2013 - 01:41
#4
Escrito 07 julio 2013 - 01:44
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
#5
Escrito 07 julio 2013 - 01:49
procedure TFMain.ConectaraBD1Click(Sender: TObject); begin with DM1.ADOConnection1 do begin if Connected then begin Messagedlg('YA ESTA CONECTADO A BD',mtWarning,[mbok],0); Exit end; try //envio cadena de conexion DM1.ADOConnection1.ConnectionString:='Provider=MSDASQL.1;Persist Security Info=False;Data Source=db_faltas'; Connected:=True; Messagedlg('EXITO AL CONECTAR A BD',mtConfirmation,[mbok],0); //habilito boton inicar sesion MMenu.Items[0].Items[1].Enabled:=True; Exit except raise Exception.Create('ERROR AL CONECTAR A BD'); end; end; 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.
#6
Escrito 07 julio 2013 - 01:56
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:
Procedure conectado; begin if DM1.ADOConnection1.Connected = true then // else Showmessage('la BD perdio la conexion'); end;
Saludos
#7
Escrito 07 julio 2013 - 02:13
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

Ese mensaje de MYSQL quiero capturar en delphi para que DELPHI me tire un mensaje de ERROR EN LA CONEXION.
#8
Escrito 07 julio 2013 - 02:21
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
#9
Escrito 07 julio 2013 - 02:37
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 ?
#10
Escrito 07 julio 2013 - 02:41
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
#11
Escrito 08 julio 2013 - 04:08
#12
Escrito 08 julio 2013 - 12:11
[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
#13
Escrito 08 julio 2013 - 05:03
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.
type TForm1 = class(TForm) ApplicationEvents1: TApplicationEvents; procedure ApplicationEvents1Exception(Sender: TObject; E: Exception); private FErrores: TStringList; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.ApplicationEvents1Exception(Sender: TObject; E: Exception); const SErrorMsgFile = 'mensajes.txt'; var I: Integer; S, N: string; begin if not Assigned(FErrores) then begin FErrores := TStringList.Create; S := ExtractFilePath(GetModuleName(HInstance)) + SErrorMsgFile; if FileExists(S) then FErrores.LoadFromFile(S); end; S := E.Message; for I := 0 to FErrores.Count - 1 do begin N := FErrores.Names[I]; if Pos(N, S) <> 0 then begin S := FErrores.Values[N]; Break; end; end; MessageDlg(S, mtError, [mbOk], 0); 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.
#14
Escrito 12 julio 2013 - 08:40
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
type TForm1 = class(TForm) ApplicationEvents1: TApplicationEvents; procedure ApplicationEvents1Exception(Sender: TObject; E: Exception); private FErrores: TStringList; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.ApplicationEvents1Exception(Sender: TObject; E: Exception); const SErrorMsgFile = 'mensajes.txt'; var I: Integer; S, N: string; begin if not Assigned(FErrores) then begin FErrores := TStringList.Create; S := ExtractFilePath(GetModuleName(HInstance)) + SErrorMsgFile; if FileExists(S) then FErrores.LoadFromFile(S); end; S := E.Message; for I := 0 to FErrores.Count - 1 do begin N := FErrores.Names[I]; if Pos(N, S) <> 0 then begin S := FErrores.Values[N]; Break; end; end; MessageDlg(S, mtError, [mbOk], 0); 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