Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Problema al comenzar transaccion (https://www.clubdelphi.com/foros/showthread.php?t=88698)

cipce22 17-07-2015 02:46:04

Problema al comenzar transaccion
 
Hola a todos, estoy utilizando delphi 2010, windows 8 y los componentes de Interbase (TIBQuery,IBTransaction,TIBDatabase) alojados en un modulo de datos(dm) realizando una aplicacion que busque ciertos registros en base a un CAMPO y un VALOR que solicito al cliente, los muestro posteriorment en un grid, de la sig. manera

Código Delphi [-]
qsql:='select matricul.id,matricula,bastidor, marca, modelo, ano, placasauto, cf1 || '+chr(39)+' '+chr(39)+' || apellido1 || '+chr(39)+' '+chr(39)+' || apellido2 as NOMBRE'+  ' from 
matricul join clientes on matricul.rfnclientes=clientes.id' +' where '+Cb_Identificador.Text+' like '+CHR(39)+'%'+Edit_valor.Text+CHR(39);  

  dm.IBDatabase1.Open;  
       with dm.IBQuery1 do      
          begin                                              
              if Transaction.Active then                  
             begin                                           
                 Transaction.Commit;             
              end;          
       Transaction.StartTransaction;            
      SQL.Clear;          
      SQL.Add(qsql);         
      OPEN;                                         
      Transaction.CommitRetaining;                   
    end;




Hasta aqui todo sigue bien, despues de eso debo actualizar los registros no seleccionados, hice este procedimiento para lograrlo:
Código Delphi [-]
procedure  UPDATE_f(dataset: TIBQuery; query: string; msgerror: string);
 begin 
  with dataset do                                    
   begin                                  
       Transaction.StartTransaction;            
       SQL.Clear;                            
       SQL.Add(query);                         
       Prepare;                                
       params.ParamByName('id_matricula_nvo').AsInteger:=Form_Seleccion.campo_id_oficial;           
       ExecSQL;        
       try                     
          Transaction.Commit;                
       except               
          on E: Exception do       
          begin                     
             Application.MessageBox( PChar( E.Message ), PChar( msgerror ), MB_ICONSTOP );                               
             dataset.Transaction.Rollback;                                         
          end;                           
       end;                        
    end; 
end;

Al ser muchas querys a actualizar distintas la ejecuto así
Código Delphi [-]
UPDATE_f(dm.IBQuery1,sqql,'Error al actualizar HISTOMAT');

Este lo uso dandole el valor de la query que voy armando en otra parte, el problema es el siguiente y por el cual pongo todo lo anterior:
al llegar a la linea de la funcion, me da una violacion de acceso
Código Delphi [-]
Transaction.StartTransaction;

Ya intenté hacerlo sin el procedure(digamos que escrito una y otra vez, en cada parte), ya probé duplicando los componentes de la base de datos(obviamente cambiando los nombres) y
nada, sigo con el error de la violacion, tambien aparece si en esa linea o en el procedimiento pongo lo sig. :
Código Delphi [-]
dm.IBDatabase1.Close;


alguien podria ayudarme? o darme alguna pista de por donde atacar el problema?

Neftali [Germán.Estévez] 17-07-2015 08:57:19

Ejecuta paso a paso el código.
Normalmemte el error de "Access Violation" da cuando utilizas un objeto que no está correctamente asignado.

cipce22 17-07-2015 21:47:37

Fue el primer paso
 
Ejecuté paso a paso, todo va bien hasta llegar a esa linea, he hecho mas pruebas y llegando a la funcion, haga lo que haga, ya no puedo cerrar la transaccion, ya no me permite un commit, rollback, cerrar el dataset o incuso intentar cerrar el componente de la BD
¿Tendrá algo que ver con que el primer select fue mostrado en un dbgrid y no me permite cerrar la conexion?

Estoy sacando chispas y no logro hacer funcionar algo relativamente "sencillo"

) :

Casimiro Notevi 17-07-2015 22:39:18

Cita:

Empezado por cipce22 (Mensaje 494572)
Ejecuté paso a paso, todo va bien hasta llegar a esa linea, he hecho mas pruebas y llegando a la funcion, haga lo que haga, ya no puedo cerrar la transaccion, ya no me permite un commit, rollback, cerrar el dataset o incuso intentar cerrar el componente de la BD

Y cuando llega a esa línea, qué hace. ¿Por qué dices que no puedes cerrar la transacción?, ¿sale algún mensaje?, ¿qué error muestra?

cipce22 18-07-2015 01:14:49

Mira
 
La cosa es esta

antes de llegar a esta linea (la que me muestra una violacion de acceso):
Código Delphi [-]
Transaction.StartTransaction;


puse lo siguiente, para saber si es que estaba abierta

Código Delphi [-]
if Transaction.Active then                          
                 begin                                       
      Transaction.Commit;                                
           end;

y sì. la muestra como activa comienza con el if, al llegar al commit, me da la misma violacion de acceso, por eso doy por hecho que es por la transaccion pero no estoy seguro, no entiendo del todo, he estado leyendo pero el procedimiento que uso en el select y en el update puestos al principio del post son mis unicas interacciones con la BD, no se cual podra ser el error

Casimiro Notevi 18-07-2015 20:03:22

Mira qué tienes después del commit, entonces, paso a paso, hasta la línea que da el error.

ecfisa 18-07-2015 21:35:13

Hola cipce22.

Dos consultas:
  • ¿ Form_Selección y campo_id_oficial están creados cuando llamas al procedimiento UPDATE_f ?
  • ¿ Cual es el contenido de la variable sqql cuando es enviada como argumento al procedimiento UPDATE_f ?

Saludos :)

jafera 19-07-2015 11:48:04

A ver si puede ser este el problema, en la prtimera linea de tu mensaje pones 'qsql:='select ......', luego llamas a UPDATE_f(dm.IBQuery1,sqql,'Error al actualizar HISTOMAT');

Saludos

cipce22 20-07-2015 22:07:06

Cita:

Empezado por ecfisa (Mensaje 494592)
Hola cipce22.

Dos consultas:
  • ¿ Form_Selección y campo_id_oficial están creados cuando llamas al procedimiento UPDATE_f ?
  • ¿ Cual es el contenido de la variable sqql cuando es enviada como argumento al procedimiento UPDATE_f ?
Saludos :)

Hola ecfisa, gracias por responder

Al ir con el depurador paso a paso sí me detecta el valor de Form_Seleccion.campo_id_oficial, de hecho los he mostrado en un mensaje en pantalla antes de mandarlos a la funcion, tanto como la sentencia SQL y el valor de la variable si estan ahí : (, la sentencia sql tal cual la copie del mensaje y ejecute en ibexpert y funcionó.

Estoy muy confundido he probado otras opciones, he creado otra transaccion (TIBTransaction) asosiada al mismo dataset(TIBquery) y a la misma BD (TIBDatabase), pero no la uso, solo lo he creado, al llegar a esta parte he intentado usar esa nueva transaccion y me la marca como ABIERTA, pero no he usado esta.... las sentencias del select y del update no son sobre la misma tabla ni estan ligadas en nada... hoy me tocas sufir con esto, llevo dias

cipce22 20-07-2015 22:08:10

Cita:

Empezado por jafera (Mensaje 494615)
A ver si puede ser este el problema, en la prtimera linea de tu mensaje pones 'qsql:='select ......', luego llamas a UPDATE_f(dm.IBQuery1,sqql,'Error al actualizar HISTOMAT');

Saludos


fue error de dedo, realmente si uso la variable qsql de tipo string : (

Gracias por responder jafera

ecfisa 20-07-2015 23:19:02

Hola cipe22.

Dado que recibis un error Access Violation, apunto a que estas referenciando un objeto inexistente. Como para ir circunscribiendo el error, intentá hacer esta prueba:
Código Delphi [-]
procedure  UPDATE_f(dataset: TIBQuery; query: string; msgerror: string);
begin
  (* LINEAS AGREGADAS *)
  try
    ShowMessage(Transaction.Name);
  except
    raise Exception.Create('Transaction aún no ha sido creado');
  end;
  try
    ShowMessage(dataset.ClassName);
  except
    raise Exception.Create('dataset aún no ha sido creado');
  end;
  try
    ShowMessage(Form_Seleccion.Caption);
  except
    raise Exception.Create('Form_Selection aún no ha sido creado');
  end;
  try
    ShowMessage(IntToStr(Form_Seleccion.campo_id_oficial));
  except
    raise Exception.Create('campo_id_oficial aún no ha sido creado');
  end;
  (* FIN LINEAS AGREGADAS *)

  { código original
  with dataset do                                    
   begin                                  
       Transaction.StartTransaction;            
       SQL.Clear;
       SQL.Add(query);                         
       Prepare;                                
       params.ParamByName('id_matricula_nvo').AsInteger:=Form_Seleccion.campo_id_oficial;
       ExecSQL;
       try                     
          Transaction.Commit;                
       except               
          on E: Exception do
          begin                     
             Application.MessageBox( PChar( E.Message ), PChar( msgerror ), MB_ICONSTOP );
             dataset.Transaction.Rollback;                                         
          end;
       end;                        
    end;
   }
end;

Saludos :)

cipce22 21-07-2015 01:51:19

Cita:

Empezado por ecfisa (Mensaje 494662)
Hola cipe22.

Dado que recibis un error Access Violation, apunto a que estas referenciando un objeto inexistente. Como para ir circunscribiendo el error, intentá hacer esta prueba:
Código Delphi [-]procedure UPDATE_f(dataset: TIBQuery; query: string; msgerror: string); begin (* LINEAS AGREGADAS *) try ShowMessage(Transaction.Name); except raise Exception.Create('Transaction aún no ha sido creado'); end; try ShowMessage(dataset.ClassName); except raise Exception.Create('dataset aún no ha sido creado'); end; try ShowMessage(Form_Seleccion.Caption); except raise Exception.Create('Form_Selection aún no ha sido creado'); end; try ShowMessage(IntToStr(Form_Seleccion.campo_id_oficial)); except raise Exception.Create('campo_id_oficial aún no ha sido creado'); end; (* FIN LINEAS AGREGADAS *) { código original with dataset do begin Transaction.StartTransaction; SQL.Clear; SQL.Add(query); Prepare; params.ParamByName('id_matricula_nvo').AsInteger:=Form_Seleccion.campo_id_oficial; ExecSQL; try Transaction.Commit; except on E: Exception do begin Application.MessageBox( PChar( E.Message ), PChar( msgerror ), MB_ICONSTOP ); dataset.Transaction.Rollback; end; end; end; } end;


Saludos :)

Gracias ecfisa, probando eso, todo está en su sitio, cada cosa ha sido creada y se muestran los valores en los mensajes

revisando el codigo ¿Esta linea podria ser la culpable?
Código Delphi [-]
Grid_sel.DataSource:=nil;
Grid_sel es un gridview en el cual muestro el resultado del primer select, el cual voy a tratar, con esa linea pretendo desasociar el dataset al gridview ¿es correcto?

ecfisa 21-07-2015 02:17:00

Hola cipce22.
Cita:

Empezado por cipce22 (Mensaje 494664)
revisando el codigo ¿Esta linea podria ser la culpable?
Código Delphi [-]
Grid_sel.DataSource:=nil;

Si se tratase de un TDBGrid te diría que no, pero desconozco el componente que mencionas (¿ es este gridview ?), de todos modos parece bastante improbable. Lo que esperaría es que no mostrase dato alguno pero un error de Access Violation...

Otra consulta: ¿ Existe algún TDataModule en Auto-create forms o por código, cuya creación pudiera estar en órden posterior al uso de la función ?

Saludos :)

cipce22 21-07-2015 02:58:46

Ayudaaaa
 
Cita:

Empezado por ecfisa (Mensaje 494665)
Hola cipce22.

Si se tratase de un TDBGrid te diría que no, pero desconozco el componente que mencionas (¿ es este gridview ?), de todos modos parece bastante improbable. Lo que esperaría es que no mostrase dato alguno pero un error de Access Violation...

Otra consulta: ¿ Existe algún TDataModule en Auto-create forms o por código, cuya creación pudiera estar en órden posterior al uso de la función ?

Saludos :)

Gracias ecfisa, siempre tan atento

Todos los form son auto-create, la aplicacion es pequeña. Despues de muchos intentos y busquedas, probando el codigo de la funcion update (que puse antes) en diferentes partes del codigo di con lo siguiente:

La violacion de acceso se muestra solo despues de este barrido, incluso, si lo comento, la violacion de acceso no se presenta y todo funciona bien:

Código Delphi [-]
cont_arr:=1;
   dm.IBQuery1.First;

  while not dm.IBQuery1.eof do
                             begin
                                  if not (dm.IBQuery1.FieldByName('id').AsInteger=campo_id_oficial)  then
                                        begin
                                        SetLength(Array_idmatriculas_incorr, cont_arr);
                                        Array_idmatriculas_incorr[cont_arr]:=dm.IBQuery1.FieldByName('id').AsInteger;
                                        inc(cont_arr,1);
                                        end;
                             dm.IBQuery1.Next;
                             end;

donde IBQuery1 es el dataset que utilice para la consulta SELECT, el cual es el source del grid....
de este dataset obtengo los valores de ID que modificare y los pongo en un arreglo dinamico para despues usarlos



¿alguien tiene idea de por qué este ciclo me genera una violacion de acceso despues?
Tomando en cuenta que para el update utilizo otro dataset(TIBQuery) y otra tansaccion (TIBTransaction)

cipce22 21-07-2015 03:38:38

falló
 
Cita:

Empezado por ecfisa (Mensaje 494665)
Hola cipce22.

Otra consulta: ¿ Existe algún TDataModule en Auto-create forms o por código, cuya creación pudiera estar en órden posterior al uso de la función ?

Saludos :)


Al mover el orden una de mis forms no se logra mostrar y me muestra violacion de acceso, el form que lo provoca es el ultimo en ser mostrado y el ultimo en la lista ¿así debe ser?

el error de el update continua :(

Casimiro Notevi 21-07-2015 10:02:26

Yo revisaría esta parte:
Código Delphi [-]
SetLength(Array_idmatriculas_incorr, cont_arr);
Array_idmatriculas_incorr[cont_arr]:=dm.IBQuery1.FieldByName('id').AsInteger;
inc(cont_arr,1);
Así a simple vista diría que tienes el problema ahí.

ecfisa 21-07-2015 18:55:43

Hola cipce22.

Opino igual que Casimiro, debería ser:
Código Delphi [-]
...
 cont_arr := 0; // <-
 ....
 begin
      SetLength(Array_idmatriculas_incorr, cont_arr + 1 ); // <-

      Array_idmatriculas_incorr[cont_arr]:=dm.IBQuery1.FieldByName('id').AsInteger;
      inc(cont_arr,1);
  ...

También lo podrías escribir de este modo (ahorrándote el contador):
Código Delphi [-]
...
  while not dm.IBQuery1.eof do
  begin
    if  not (dm.IBQuery1.FieldByName('id').AsInteger=campo_id_oficial)  then
    begin
      SetLength(Array_idmatriculas_incorr, Length(Array_idmatriculas_incorr) + 1 );
      Array_idmatriculas_incorr[High(Array_idmatriculas_incorr)]:= dm.IBQuery1.FieldByName('id').AsInteger;
    end;
    dm.IBQuery1.Next;
  end;
...

Otra alternativa es darle al arreglo dinámico, el tamaño de una sola vez:
Código Delphi [-]
...
  cont_arr := 0;
  SetLength(Array_idMatriculas_incorr, dm.IBQuery1.RecordCount ); // <-
  while not dm.IBQuery1.eof do
  begin
    if  not (dm.IBQuery1.FieldByName('id').AsInteger=campo_id_oficial)  then
    begin
      Array_idmatriculas_incorr[cont_arr]:= dm.IBQuery1.FieldByName('ID').AsInteger;
      Inc(cont_arr, 1);
    end;
    dm.IBQuery1.Next;  
  ...

Saludos :)

cipce22 21-07-2015 21:29:55

Funcionó
 
¡Funcionó! :D gracias


De alguna manera el cambiar este ciclo ya no generó la violación de acceso, ¿por qué la provocaba?

no me mostraba ningun error ni mostraba alguna excepcion cuando lo ponia en un bloque try

si alguien me explica esto ultimo, seria perfecto para poder evitar este error en el futuro, que para mi, es casi inexplicable :(
Agradezco a todos la ayuda

Casimiro Notevi 21-07-2015 23:30:28

Cita:

Empezado por cipce22 (Mensaje 494706)
no me mostraba ningun error ni mostraba alguna excepcion cuando lo ponia en un bloque try

Eso te pasa por no poner el código real que estás usando.
Lo habríamos visto al momento.

cipce22 22-07-2015 00:42:46

Apuntado
 
Cita:

Empezado por Casimiro Notevi (Mensaje 494710)
Eso te pasa por no poner el código real que estás usando.
Lo habríamos visto al momento.

Tienes razón :D, la proxima vez lo posteare completo en caso de no ser tan grande, aunque sigo con la duda de cual es la razon para que ese ciclo me generara la violacion :confused::confused::confused:


La franja horaria es GMT +2. Ahora son las 04:16:52.

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