Consulta influenciando na transação

Delphi

13/08/2010

Achei que havia resolvido. Mas não! Neste exemplo de código abaixo, a presença do select, não permite que o rollback ocorra de forma correta.

var


  T_ID1: TTransactionDesc;


begin


  //-


  T_ID1.TransactionID  := 1;


  T_ID1.IsolationLevel := xilREADCOMMITTED;


  SQLConnection1.StartTransaction(T_ID1);





  //-


  ClientDataSet1.Open;


  ClientDataSet1.First;





  //-


  try


    while not (ClientDataSet1.Eof) do


      begin


        //-  ESTE É O SELECT <==========


        SQLQuery2.Close;


        SQLQuery2.SQL.Text := 'SELECT CAB_NUM FROM CABECALHO WHERE 
CAB_ID = ' + QuotedStr(IntToStr(ClientDataSet1IT_FKCAB_ID.AsInteger));


        SQLQuery2.Open;





        //-


        ClientDataSet1.Edit;


        ClientDataSet1IT_NUM.AsInteger  := SQLQuery2.Fields.Fields[0].AsInteger;


        ClientDataSet1.Post;





        //-


        SQLQuery1.Close;


        SQLQuery1.SQL.Text := 'UPDATE CABECALHO SET CAB_NUM = ' + 
QuotedStr(IntToStr(SQLQuery2.Fields.Fields[0].AsInteger + 1)) + ' WHERE 
CAB_ID = ' + QuotedStr(IntToStr(ClientDataSet1IT_FKCAB_ID.AsInteger));


        SQLQuery1.ExecSQL();





        //-


        ClientDataSet1.Next;


      end;


    //-


    if ClientDataSet1.ApplyUpdates(0) = 0 then


      SQLConnection1.Commit(T_ID1)


    else


      SQLConnection1.Rollback(T_ID1)


  except


    SQLConnection1.Rollback(T_ID1);


  end;



Sem o select, o rollback funciona. Alguém já passou por esta experiência?? Como manter o select e ele não influenciar no rollback?

Continuo pesquisando. Caso encontre uma reposta posto. Mas se alguem puder contribuir...

Uso Firebird 2.0 com Drive UIB

[]'s
Junior Miranda

Junior Miranda

Curtidas 0

Respostas

Marcos Iwazaki

Marcos Iwazaki

13/08/2010

Amigo...
Qdo vc diz que o select influencia, em que sentido esta influenciando?

 
GOSTEI 0
Junior Miranda

Junior Miranda

13/08/2010

Amigo...
Qdo vc diz que o select influencia, em que sentido esta influenciando?

 


Obrigado pela atenção! No exemplo que postei, são alterados os valores em duas tabelas. O select recupera o valor da tabela CABECALHO e atribui a tabela ITENS(ClientDataset1). O update incrementa o valor da tabela CABECALHO. O problema é que com a presença do select, se for levantada uma excessão, apenas a tabela de ITENS sofre o rollback. A tabela CABECALHO é alterada. Se retiro o select e simulo...  o rollback funciona!    

[]'s
GOSTEI 0
Marcos Iwazaki

Marcos Iwazaki

13/08/2010

Bom parece tudo normal no código...

Mas uma coisa que pode causar problema ae é o ClientDataSet.
Pois qdo vc faz operações nele, ele guarda os valores em memoria, mesmo depois de ter feito rollback o dados alterados ainda estão em memoria. Isso quer dizer se for fazer rollback vc tem q cancelar o clientDataSet tbm.

Veja se isso resolve. 
GOSTEI 0
Junior Miranda

Junior Miranda

13/08/2010

Na minha estrutura original eu já faço isso. Eu não consigo entender!


[]'s
GOSTEI 0
Junior Miranda

Junior Miranda

13/08/2010

O problema está no bendito drive UIB! Como eu não encontrava nenhum problema aparente, resolvir testar a mesma situação com o drive interbase e firebird(Delphi 2010). Funcionou como deveria! Agora vou ter de repensar a rotina para driblar esta situação. Não poderei mudar o drive de imediato. É mole?

Amigo socram, responda novamente esta thread para finalizarmos e vc ficar o crédito pela atenção dada.


[]'s
GOSTEI 0
Junior Miranda

Junior Miranda

13/08/2010

O problema está no bendito drive UIB! Como eu não encontrava nenhum problema aparente, resolvir testar a mesma situação com o drive interbase e firebird(Delphi 2010). Funcionou como deveria! Agora vou ter de repensar a rotina para driblar esta situação. Não poderei mudar o drive de imediato. É mole?

Amigo socram, responda novamente esta thread para finalizarmos e vc ficar o crédito pela atenção dada.


[]'s

Durante os estudos, encontrei várias citações para este problema(Nenhuma solução mantendo o drive). Segundo estas citações, a questão é como o UIB gerência as transações. O caso é que o SELECT executado dentro de uma transação(Utilizando o drive UIB), comita a mesma antes do COMMIT propriamente dito. Então quando o rollback é executado, não há o que voltar.

Baseado nisso. Tentei até algo como:

var
T_ID1: TTransactionDesc;
begin
  //-
  ClientDataSet1.Open;
  ClientDataSet1.First;
  //-
  try
    while not (ClientDataSet1.Eof) do
      begin
        //-
        SqlQuery2.Close;
        SqlQuery2.Sql.Text := 'SELECT CAB_NUM FROM CABECALHO WHERE CAB_ID = ' + QuotedStr(IntToStr(ClientDataSet1IT_FKCAB_ID.AsInteger));
        SqlQuery2.open;

        ClientDataSet1.Edit;
        ClientDataSet1IT_NUM.AsInteger  := SqlQuery2.Fields.Fields[0].AsInteger;
        ClientDataSet1.Post;

        //-
        SQLQuery1.Close;
        SQLQuery1.SQL.Text := 'UPDATE CABECALHO SET CAB_NUM =' + QuotedStr(IntToStr(SqlQuery2.Fields.Fields[0].AsInteger + 1)) +  ' WHERE CAB_ID =' + QuotedStr(IntToStr(ClientDataSet1IT_FKCAB_ID.AsInteger));
        SQLQuery1.ExecSQL();

        //-
        ClientDataSet1.Next;
      end;
  //-
  T_ID1.TransactionID  := 1;
  T_ID1.IsolationLevel := xilREADCOMMITTED;
  SQLConnection1.StartTransaction(T_ID1);
  //-
  if ClientDataSet1.ApplyUpdates(0) = 0 then
    SQLConnection1.Commit(T_ID1);
  except
    SQLConnection1.Rollback(T_ID1);
  end;


Ou seja, só dou o start na transação depois do fim do laço. Mas mesmo assim, o problema persiste. Continuo os estudos para resolver este problema. Se alguém puder contribuir...

[]'s
GOSTEI 0
Junior Miranda

Junior Miranda

13/08/2010

Só corrijindo o código
var
T_ID1: TTransactionDesc;
begin
  //-
  ClientDataSet1.Open;
  ClientDataSet1.First;
  //-
  try
    while not (ClientDataSet1.Eof) do
      begin
        //-
        SqlQuery2.Close;
       
 SqlQuery2.Sql.Text := 'SELECT CAB_NUM FROM CABECALHO WHERE CAB_ID = ' +
 QuotedStr(IntToStr(ClientDataSet1IT_FKCAB_ID.AsInteger));
        SqlQuery2.open;

        ClientDataSet1.Edit;
        ClientDataSet1IT_NUM.AsInteger  := SqlQuery2.Fields.Fields[0].AsInteger;
        ClientDataSet1.Post;

        //-
        SQLQuery1.Close;
       
 SQLQuery1.SQL.Text := 'UPDATE CABECALHO SET CAB_NUM =' + 
QuotedStr(IntToStr(SqlQuery2.Fields.Fields[0].AsInteger + 1)) +  ' WHERE
 CAB_ID =' + QuotedStr(IntToStr(ClientDataSet1IT_FKCAB_ID.AsInteger));
        SQLQuery1.ExecSQL();

        //-
        ClientDataSet1.Next;
      end;
  //-
  T_ID1.TransactionID  := 1;
  T_ID1.IsolationLevel := xilREADCOMMITTED;
  SQLConnection1.StartTransaction(T_ID1);
  //-
  if ClientDataSet1.ApplyUpdates(0) <> 0 then
    Raise Exception.Create('');
  //- 
  SQLConnection1.Commit(T_ID1);
  except
    SQLConnection1.Rollback(T_ID1);
  end;


[]'s
GOSTEI 0
Junior Miranda

Junior Miranda

13/08/2010

Onde está escrito "Corrijindo", leiam Corrigindo. Desculpem!!!!

[]'s


GOSTEI 0
Marco Salles

Marco Salles

13/08/2010

Como vc mesmo testou o controle de Transação do Delphi 2010 pode desfazer ate o applayUpdades Tem ate um threads sobre isto aqui mesmo     o que eu tentaria é ao invez de utilizar o clientDataSet     ClientDataSet1.Edit; 
  ClientDataSet1IT_NUM.AsInteger  := SqlQuery2.Fields.Fields[0].AsInteger; 
  ClientDataSet1.Post;   Faria com Update ... Igualmente vc Fez com o          SQLQuery1.SQL.Text := 'UPDATE CABECALHO SET CAB_NUM =' + QuotedStr(IntToStr(SqlQuery2.Fields.Fields[0].AsInteger + 1)) +  ' WHERE CAB_ID =' + QuotedStr(IntToStr(ClientDataSet1IT_FKCAB_ID.AsInteger));
        SQLQuery1.ExecSQL();
  Deixaria a Transação no Inicio do Bloco ( apesar que não é bom uma Transação ficar muito Tempo Aberta)   e no fim comitaria ou desfazeria   Me parece estranho é vc misturar o controle Transacional do MIDAS ( ApplayUpdates ) com a Transação propriamente dita
GOSTEI 0
Junior Miranda

Junior Miranda

13/08/2010

Como vc mesmo testou o controle de Transação do Delphi 2010 pode desfazer ate o applayUpdades Tem ate um threads sobre isto aqui mesmo     o que eu tentaria é ao invez de utilizar o clientDataSet     ClientDataSet1.Edit; 
  ClientDataSet1IT_NUM.AsInteger  := SqlQuery2.Fields.Fields[0].AsInteger; 
  ClientDataSet1.Post;   Faria com Update ... Igualmente vc Fez com o          SQLQuery1.SQL.Text := 'UPDATE CABECALHO SET CAB_NUM =' + QuotedStr(IntToStr(SqlQuery2.Fields.Fields[0].AsInteger + 1)) +  ' WHERE CAB_ID =' + QuotedStr(IntToStr(ClientDataSet1IT_FKCAB_ID.AsInteger));
        SQLQuery1.ExecSQL();
  Deixaria a Transação no Inicio do Bloco ( apesar que não é bom uma Transação ficar muito Tempo Aberta)   e no fim comitaria ou desfazeria   Me parece estranho é vc misturar o controle Transacional do MIDAS ( ApplayUpdates ) com a Transação propriamente dita


Já testei desta forma também! O problema é que como o select está dentro da transação e em loop, a cada volta, ele (o select), commita o ExecSql anterior. Isto antes do commit propriamente dito. Então, quando há uma excessão, o rollback não funcionaria como devido. Quero garantir a atomicidade através da transação. Mas o bendito drive UIB não permite(Sob esta condição). Como não posso mudar o drive no momento, preciso encontrar uma alternativa(na aplicação). Mas até agora nada funcionou.

[]'s
GOSTEI 0
Marco Salles

Marco Salles

13/08/2010


Já testei desta forma também! O problema é que como o select está dentro da transação e em loop, a cada volta, ele (o select), commita o ExecSql anterior. Isto antes do commit propriamente dito. Então, quando há uma excessão, o rollback não funcionaria como devido. Quero garantir a atomicidade através da transação. Mas o bendito drive UIB não permite(Sob esta condição). Como não posso mudar o drive no momento, preciso encontrar uma alternativa(na aplicação). Mas até agora nada funcionou.

[]'s
  Acho que vc não entendeu . Ou pelo menos não tem nehuma Logica   Eu não so estou sugerindo para que vc coloque o Inicio da Transação antes do Loop. Isto eu ja vi que vc fez O Que estou sugerindo é que alem disso , não use o clientDataSet , use Dois Updates (dois ExecSql) um para cada operação ... Não vejo como comitar se a Transação esta aberta Não vejo pq Comitar um Update e não comitar o Outro ... A Atomicidade é exatamente isto
GOSTEI 0
Junior Miranda

Junior Miranda

13/08/2010

  Acho que vc não entendeu . Ou pelo menos não tem nehuma Logica   Eu não so estou sugerindo para que vc coloque o Inicio da Transação antes do Loop. Isto eu ja vi que vc fez O Que estou sugerindo é que alem disso , não use o clientDataSet , use Dois Updates (dois ExecSql) um para cada operação ... Não vejo como comitar se a Transação esta aberta Não vejo pq Comitar um Update e não comitar o Outro ... A Atomicidade é exatamente isto


Que parte do já utilizei desta forma vc não entendeu????? 


Já testei desta forma também! O problema é que como o select está dentro da transação e em loop, a cada volta, ele (o select), commita o ExecSql anterior. Isto antes do commit propriamente dito. Então, quando há uma excessão, o rollback não funcionaria como devido. Quero garantir a atomicidade através da transação. Mas o bendito drive UIB não permite(Sob esta condição). Como não posso mudar o drive no momento, preciso encontrar uma alternativa(na aplicação). Mas até agora nada funcionou.



Me mostra nesta minha última citação, onde indico o uso do clientdaset. Eu poderia devolver a sua ofensa. Mas não vou fazer isso não.  Se eu fizesse isto, estaria me comportando como moleque. Coisa que não sou. Dá uma pesquisada no drive UIB e veja se o que eu estou dizendo é uma mentira. O que seria do mundo se fossem estes "Senhores do Conhecimento".

[]'s



GOSTEI 0
Marco Salles

Marco Salles

13/08/2010

 Me mostra nesta minha última citação, onde indico o uso do clientdaset. Ultima Citação Postado em 13/08/2010 as 09:58:53   var
T_ID1: TTransactionDesc;
begin
  //-
  ClientDataSet1.Open;
  ClientDataSet1.First;
  //-
  try
    while not (ClientDataSet1.Eof) do
      begin
        //-
        SqlQuery2.Close;
        SqlQuery2.Sql.Text := 'SELECT CAB_NUM FROM CABECALHO WHERE CAB_ID = ' + QuotedStr(IntToStr(ClientDataSet1IT_FKCAB_ID.AsInteger));
        SqlQuery2.open;

        ClientDataSet1.Edit;
        ClientDataSet1IT_NUM.AsInteger  := SqlQuery2.Fields.Fields[0].AsInteger;
        ClientDataSet1.Post;
.............continua Codigo   if ClientDataSet1.ApplyUpdates(0) <> 0 then .... Finaliza o codigo end;

 
Eu poderia devolver a sua ofensa. Mas não vou fazer isso não.  Se eu fizesse isto, estaria me comportando como moleque. Coisa que não sou.
  concordo em partes Aqui não teve ofensa . Apenas um BURRO (EU) tentando de graçã ajudar alguem.. Mas mereço. Minha mulher ja disse isto.Obrigado  
Dá uma pesquisada no drive UIB e veja se o que eu estou dizendo é uma mentira. O que seria do mundo se fossem estes "Senhores do Conhecimento".
concordo tb em partes O que seria de Algumas pessoas sem estes senhores do conhecimento .....
Sem
[]'s
  paramos por aqui ... OK ??? Sem réplica e sem Tréplica
GOSTEI 0
POSTAR