PDA

Ver la Versión Completa : Actualizacion BD en Ado


principiante22
04-10-2008, 10:08:38
Saludos, Tengo dos TAdoQuery, 1 de ellos es en el que realizo una entrada y este en su evento AfterPost tiene el siguiente codigo:

procedure TForm1.ADOQuery1AfterPost(DataSet: TDataSet);
begin
Adoquery2.close;
Adoquery2.open;
Adoquery1.Close;
Adoquery1.Open;
end;


Pero el Adoquery2 (que tiene conectada un DataSource para presentar los datos en un dbgrid) no se actualiza de los nuevos datos, SOLO lo hace (actualizarse) de ves en cuando, no siempre :confused:.

Espero haberme explicado bien, muchas gracias y bye :D

olbeup
04-10-2008, 13:51:20
Si lo cambios lo realizas en el ADOQuery1, tiene que cerrar primero el que realizas los cambio y luego abrir las base de datos.

Un saludo.

principiante22
04-10-2008, 14:03:09
Aunque invierto el orden, obtengo el mismo problema :confused:

donki
04-10-2008, 19:50:43
Revisa el parámetro CursorType de la AdoQuery1. Si es de tipo ctUpdateBatch ("Creo que se llama asi") los datos no se actualizan directamente. Necesitas hacer una llamada antes. Canviar esta propiedad a ctStatic para que te haga el post en la BD y te actualize la AdoQuery2.

principiante22
06-10-2008, 23:24:57
Esta de tipo ctStatic y como quiera no funciona :confused:. Pero gracias por tu interes.

donki
07-10-2008, 08:13:00
Mira tambien que el locktype sea ltOptimistic.

Saludos

principiante22
07-10-2008, 11:49:53
Esta igual, el ADOQuery1 y el 2 tienen todas sus propiedades que vienen por default

tefots
08-10-2008, 16:34:24
al ejecutar el afterpost del adoquery1 no significa que se guarden los datos en la base de datos , simplemente es el afterpost del objeto tadoquery que estas usando. hasta que no finalices la transaccion , los datos no los vas a ver desde otros querys.


lo que quiero decir es que si no haces commit (en el afterpost o donde quieras) , cualquier otro adoquery que intente mostrar esos datos no los va a ver.

yo pondria algo como esto.


procedure TForm1.ADOQuery1AfterPost(DataSet: TDataSet);
begin
timer1.enabled:=true;
end;


y en el timer finalizas la transaccion ,
y cierras y abres el query para refrescar.


Procedure Tform1.Timer1OnTimer(Sender:Tobject)
Begin
If adoquery1.connection.intransaction then
Adoquery1.connection.CommitTrans;
Adoquery2.close; Adoquery2.open;
End;


de todas formas , yo no lo haria asi , aunque todo depende de com tengas hecha la aplicacion , y que controles tengas enlazados
Saludos.

principiante22
08-10-2008, 21:43:40
Gracias tefots por tu respuesta, pero no logro entender como es eso de:

If adoquery1.connection.intransaction then
Adoquery1.connection.CommitTrans

Si me lo puedes explicar, seria un exito :D

Caral
08-10-2008, 21:55:20
Hola
La verdad no entiendo el problema, tampoco entiendo la necesidad de una transaccion para una sola tabla o query, me parece que es como matar moscas con un cañon.
Tengo un adoquery1, este lo que hace es hacer una insercion a modificacion o lo que sea de una o varias tablas.
Ahora tengo un adoquery2, este lo que hace es ver la tabla en el formulario.
Bueno, cual es el problema?.
Hago la modificacion o lo que sea con el primero, y lo ejecuto, o lo abro, cierro y vuelvo a abrir (mas trabajo).
Luego simplemente abro y cierro el segundo query.
Donde esta lo complicado o es que me pierdo de algo?.
Saludos

principiante22
08-10-2008, 21:58:50
Luego simplemente abro y cierro el segundo query.

Bueno Caral, ese es precisamente el problema, cuando lo cierro y lo abro (que lo hago para que se actualice el query) no obtengo lo deseado, no se actualiza, solo lo hace de vez en cuando.

Caral
08-10-2008, 22:04:25
Hola
Osea tienes el viejo problema del query perezoso.:D:D
Cuando se ejecuta un query el dato se guarda en la base de datos en segundos.
Cuando ejecuto el query1, el query2 si se cierra y luego se abre tiene por que tiene que ver el dato actualizado a no ser que como dije al principio, sea un query perezoso, pero creo que ya delphi los saco del sistema.:D:D
Muy raro, muy raro.
Saludos

principiante22
08-10-2008, 22:10:58
Bueno, con la idea de tefots pude hacer algo que se adapte a lo que necesitaba, me di cuenta de que al adoquery le tomaba 5.5 segs para actualizar la base de datos, asi que puse un timer con un interval:6000 y resuelto jeje. Bueno, gracias a todos por sus respuestas ;)

Caral
08-10-2008, 22:20:42
Hola
Me alegro que lo resolvieras.
Solo para que te des una idea de como lo hago yo:

DataModule1.AC1.BeginTrans;
try
If Nueva then
QTemp.SQL.Text := 'Insert Into OrdenProd (Codorden, FechaInicio, FechaRequerido, CodUsuario, Comentarios, CodCliente, Prioridad, Enrutada, OrdenCompra) '+
'Values (' +Edit2.Text+', '+QuotedStr(Edit4.Text)+', '+QuotedStr(DateToStr(DateTimePicker1.DateTime))+', '+
QuotedStr(Edit5.Text)+', '+QuotedStr(Memo1.Text)+', '+Edit3.Text+', '+IntEdit1.Text+', True, '+QuotedStr(Edit7.Text)+')'
else
QTemp.SQL.Text := 'Update OrdenProd set FechaRequerido = '+QuotedStr(DateToStr(DateTimePicker1.DateTime))+', Comentarios = '
+QuotedStr(Memo1.Text)+', CodCliente = '+Edit3.Text+', Prioridad = '+IntEdit1.Text+
' Where CodOrden = '+Edit2.Text;

QTemp.ExecSQL;
guardada := true;
IF Nueva then
begin
QOrdProd.Requery();
QOrdProd.Last;
end
else begin
bok := QOrdProd.Bookmark;
QOrdProd.Requery();
QOrdProd.Bookmark := bok;
end;
DataModule1.AC1.CommitTrans;
If Nueva then If MessageDlg('Orden Guardada.'+#13+'¿Desea agregar items a la orden?',mtConfirmation,[mbYes,mbNo],0) = mrYes then
Nueva := False;
QOrdProd.Close;
QOrdProd.Open;
except
on E:Exception do DataModule1.AC1.RollbackTrans;
end;//try
end;
Saludos

principiante22
08-10-2008, 22:23:20
:confused::confused::confused::confused::confused::confused:

Talvez dentro de algunos 30 años yo este a ese nivel ;):p

Caral
08-10-2008, 22:27:42
Hola
Que va, no te subestimes, el mas Novato aqui soy yo, con solo un par de años en esto.
Pronto harás cosas de verdad, mucho mejor que estas.
Saludos

tefots
09-10-2008, 14:25:27
me alegro que funcionara.

todas formas eso de esperar 6 segundos para poder ver los datos desde otro query es mas que raro , rarisimo.
en teoria cuando finalizas la transaccion , los datos ya deben estár inmediatamente disponibles y debes poder verlos desde la propia aplicación o desde otra.


lo del

If adoquery1.connection.intransaction then
Adoquery1.connection.CommitTrans

lo que hace es mirar si la conexion asociada al adoquery tiene una transaccion abierta , tonces hace commit de la transaccion.

lo logico seria hacerlo directamente con el adoconnection , pero como no se si tienes algun adoconnection enlazado por eso lo puse asi.

que base de datos utilizas ?.

tienes algun adoconnection enlazado , uno por cada adoquery o uno para los dos ? , alo mejor esta ahi el problema

por cierto , lo de los querys perezosos yo nunca lo habia oido ni nunca me ha pasado , a lo mejor es que los datos se paran a tomar un café antes de que esten 'disponibles'. :)

saludos.


Bueno, con la idea de tefots pude hacer algo que se adapte a lo que necesitaba, me di cuenta de que al adoquery le tomaba 5.5 segs para actualizar la base de datos, asi que puse un timer con un interval:6000 y resuelto jeje. Bueno, gracias a todos por sus respuestas ;)

principiante22
09-10-2008, 14:56:37
tefots, use una base de datos de access y no tengo ningun adoconnection, pero despreocupate, aunque dure 6 segs para estar disponible, para lo que necesito, esta mas que bueno. Gracias de nuevo por tu interes ;)

koalasoft
04-03-2017, 02:17:28
Hola
Me alegro que lo resolvieras.
Solo para que te des una idea de como lo hago yo:

DataModule1.AC1.BeginTrans;
try
If Nueva then
QTemp.SQL.Text := 'Insert Into OrdenProd (Codorden, FechaInicio, FechaRequerido, CodUsuario, Comentarios, CodCliente, Prioridad, Enrutada, OrdenCompra) '+
'Values (' +Edit2.Text+', '+QuotedStr(Edit4.Text)+', '+QuotedStr(DateToStr(DateTimePicker1.DateTime))+', '+
QuotedStr(Edit5.Text)+', '+QuotedStr(Memo1.Text)+', '+Edit3.Text+', '+IntEdit1.Text+', True, '+QuotedStr(Edit7.Text)+')'
else
QTemp.SQL.Text := 'Update OrdenProd set FechaRequerido = '+QuotedStr(DateToStr(DateTimePicker1.DateTime))+', Comentarios = '
+QuotedStr(Memo1.Text)+', CodCliente = '+Edit3.Text+', Prioridad = '+IntEdit1.Text+
' Where CodOrden = '+Edit2.Text;

QTemp.ExecSQL;
guardada := true;
IF Nueva then
begin
QOrdProd.Requery();
QOrdProd.Last;
end
else begin
bok := QOrdProd.Bookmark;
QOrdProd.Requery();
QOrdProd.Bookmark := bok;
end;
DataModule1.AC1.CommitTrans;
If Nueva then If MessageDlg('Orden Guardada.'+#13+'¿Desea agregar items a la orden?',mtConfirmation,[mbYes,mbNo],0) = mrYes then
Nueva := False;
QOrdProd.Close;
QOrdProd.Open;
except
on E:Exception do DataModule1.AC1.RollbackTrans;
end;//try
end;
Saludos

Estimado, me podrias explicar para que usar el Recuery y por que para cuando actualizas usas esos parámetros?
Gracias !!

ecfisa
04-03-2017, 11:08:41
Hola.
Estimado, me podrias explicar para que usar el Recuery ...
Ví que en otro hilo (http://www.clubdelphi.com/foros/showthread.php?t=60515) consultaste sobre la funcionalidad del método Requery, espero que esta traducción de la ayuda de Delphi conteste tu duda:

...
Llame a Requery para actualizar el conjunto de registros. Requery actualiza el conjunto de datos al volver a ejecutar el comando original o la instrucción SQL que produjo el conjunto de registros.

Los efectos de Requery son los mismos que llaman el método Close del dataset y luego su método Open. Sin embargo, hay circunstancias en las que un medio de actualizar el conjunto de registros es mejor que el otro. Los valores en propiedades como CursorLocation, CursorType y LockType no se pueden cambiar mientras el conjunto de datos está abierto, por lo que Requery sólo puede actualizar el conjunto de registros utilizando los valores existentes en estas propiedades. Para actualizar el conjunto de registros utilizando valores diferentes para estas propiedades, efectúe la actualización mediante los métodos Close y Open.
...


Saludos :)

koalasoft
04-03-2017, 16:58:34
Hola.

Ví que en otro hilo (http://www.clubdelphi.com/foros/showthread.php?t=60515) consultaste sobre la funcionalidad del método Requery, espero que esta traducción de la ayuda de Delphi conteste tu duda:


Saludos :)

Muchas gracias estimado ..

Mi pregunta relacionado a esto fue que he intentado que mi procedimiento para actualizar un registro lo hace bien, puesto que al intentar actualizar me sale el siguiente mensaje:

---------------------------
Debugger Exception Notification
---------------------------
Project CTRO.exe raised exception class EOleException with message 'No se puede encontrar la fila para su actualización: algunos valores han cambiado desde la última vez que se leyó'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------

Te comento rapido, antes mi base de datos mysql (mariadb) estaba en un servidor Windows, por necesidades exporte la base de datos ahora a un servidor Linux, al querer usar el sistema nuevamente me aparece este mensaje al querer actualizar un registro, cosa que antes en el anterior servidor no lo hacia.

Mi codigo de actualización es el siguiente:


with ADOQuery1 do
begin
Close;
SQL.Clear;
SQL.Add('SELECT * FROM ONTs ');
SQL.Add('WHERE MAC_ONT LIKE ' +quotedstr('%' + Edit1.Text + '%')+' ');
Open;
if isEmpty Then
begin
AdoQuery1.Close; // cierro la tabla.
AdoQuery1.Open; // abro la Tabla
msError('No se encuentra registrado, Favor verifica los datos.','ERROR: ID MAC');
ADOQuery1.Active := False;
Edit1.SetFocus;
exit;
End
Else // En caso de Si haber un resultado
Begin
If MessageDlg('¿Está seguro que desea ACTUALIZAR el registro? ',mtConfirmation,[mbYes,mbNo],0) = mrYes then
begin
Alta_ONT.Cursor:= crSQLWait;
DMod1.ADOConnection1.BeginTrans; // Inicio la Transacción
try
ADOQuery1.Edit; // Editar la Tabla
ADOQuery1.FieldByName('MOD_ONT').AsString := ComboBox1.Text;
ADOQuery1.FieldByName('SERIE_ONT').AsString := Edit2.Text;
ADOQuery1.FieldByName('PON_ONT').AsString := Edit3.Text;
ADOQuery1.FieldByName('ONT_S').AsString := Edit4.Text;
ADOQuery1.FieldByName('SSID_ONT').AsString := Edit5.Text;
ADOQuery1.FieldByName('KEYWIFI_ONT').AsString := Edit6.Text;
ADOQuery1.FieldByName('IP_ONT').AsString := Edit7.Text;
ADOQuery1.FieldByName('ESTATUS_ONT').AsString := ComboBox2.Text;
ADOQuery1.Post; // Guardo Datos;

if DMod1.ADOConnection1.InTransaction then
Begin
DMod1.AdoConnection1.CommitTrans; // actualizo la BD
AdoQuery1.Close; // cierro la tabla.
AdoQuery1.Open; // abro la Tabla
Alta_ONT.Cursor:= crDefault;
MSG:='EL Registro ONU [MAC: '+ Edit1.Text + ' - MODELO: ' + ComboBox1.Text + ' - SERIE: '+ Edit2.Text +' - ONT/s: ' + Edit4.Text + ' ] - SE MODIFICO/ACTUALIZO Satisfactoriamente';
Application.MessageBox(PChar(MSG), 'Atención',MB_ICONINFORMATION );
LimpiarCampos([Edit1,Edit2,Edit3,Edit4,Edit5,Edit6,Edit7,ComboBox1,Combobox2]);
DesactivarCampos([Edit1,Edit2,Edit3,Edit4,Edit5,Edit6,Edit7,ComboBox1,Combobox2]);
// -- Inicio Botones
CargarBotonesInicio;
// -- Fin Botones
Alta_ONT.Cursor:= crDefault;
ADOQuery1.Active := False;
bnuevo.SetFocus;
End;
except
on E:Exception do // Si hay Error de Conexión
begin
DMod1.AdoConnection1.RollbackTrans;
Alta_ONT.Cursor:= crDefault;
ADOQuery1.Active := False;
MSG:='Ocurrió un error al guardar los datos: ' + E.Message;
Application.MessageBox(PChar(MSG),'ERROR !!!', MB_ICONSTOP );
Abort;
exit;
end; // on
End; // try
End
Else
Begin
AdoQuery1.Close; // cierro la tabla.
AdoQuery1.Open; // abro la Tabla
Alta_ONT.Cursor:= crDefault;
ADOQuery1.Active := False;
msInfo('¡CANCELADO POR EL USUARIO!.','Atención Proceso Cancelado..');
BCancelar.SetFocus;
exit;
End;
End;

ecfisa
04-03-2017, 19:56:27
Hola.

Mi pregunta relacionado a esto fue que he intentado que mi procedimiento para actualizar un registro lo hace bien, puesto que al intentar actualizar me sale el siguiente mensaje:

---------------------------
Debugger Exception Notification
---------------------------
Project CTRO.exe raised exception class EOleException with message 'No se puede encontrar la fila para su actualización: algunos valores han cambiado desde la última vez que se leyó'. Process stopped. Use Step or Run to continue.
---------------------------
OK Help
---------------------------

Te comento rapido, antes mi base de datos mysql (mariadb) estaba en un servidor Windows, por necesidades exporte la base de datos ahora a un servidor Linux, al querer usar el sistema nuevamente me aparece este mensaje al querer actualizar un registro, cosa que antes en el anterior servidor no lo hacia.

Entiendo entonces, que tu programa funcionaba bién hasta que realizaste el cambio. Revisa en estos enlaces donde se menciona dicho error a ver si alguno de los casos se corresponde con el tuyo o te orienta al respecto:

No se pudo encontrar la fila para su actualización (https://www.clubdelphi.com/foros/showthread.php?t=22677)
Extraño fallo SQL Server Delphi 7 (http://www.clubdelphi.com/foros/showthread.php?t=74218)
Problemas al actualizar Access (https://www.clubdelphi.com/foros/showthread.php?t=39420)
Error inesperado funcionaba bien (https://www.clubdelphi.com/foros/showthread.php?t=76678)


Saludos :)