Consulta influenciando na transação
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.
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
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
Curtidas 0
Respostas
Marcos Iwazaki
13/08/2010
Amigo...
Qdo vc diz que o select influencia, em que sentido esta influenciando?
Qdo vc diz que o select influencia, em que sentido esta influenciando?
GOSTEI 0
Junior Miranda
13/08/2010
Amigo...
Qdo vc diz que o select influencia, em que sentido esta influenciando?
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
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.
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
13/08/2010
Na minha estrutura original eu já faço isso. Eu não consigo entender!
[]'s
[]'s
GOSTEI 0
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
Amigo socram, responda novamente esta thread para finalizarmos e vc ficar o crédito pela atenção dada.
[]'s
GOSTEI 0
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
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
13/08/2010
Só corrijindo o código
[]'s
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
13/08/2010
Onde está escrito "Corrijindo", leiam Corrigindo. Desculpem!!!!
[]'s
[]'s
GOSTEI 0
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
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
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
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
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
GOSTEI 0
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
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;
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
GOSTEI 0