DBExpress Controle de Transacao

11/02/2013

31

Boa tarde,
até entao sempre trabalhei com zeos e postgres, porem me surgiu um projeto que vou ter q usar o Firebird e nao tenho muita experiencia com esta situacao, gostaria se alguem pudesse me dar algumas dicas sobre a seguinte situacao
Estou utilizando "Delphi XE3" pra conexao vou utilizar os componentes da paleta "DBExpress"

eu precisaria fazer o controle de Transação ?
ex:
TSQLConection1.StartTransaction();

ou o DBExpress faz este controle automatico de der algum erro ele da um roolback automatico ou nao
eu preciso dar um TSQLConection1.roolback();

como ficaria no caso de multiplas transacoes ?

nao vou utilizar ClientDaset

vou usar assim
TSQLConection1 => TSQLQuerry

TSQLQuerry1.close;
TSQLQuerry1.sql.clear;
TSQLQuerry1.sql.add(''Insert into teste(codigo,nome)values(:a1,:a2)'');
TSQLQuerry1.params[0].asinteger:=1;
TSQLQuerry1.params[1].asstring:=''Teste'';
TSQLQuerry.ExecSQL;

+/- assim estou utlizando





Responder

Post mais votado

14/02/2013

Olá!

Usando DBX, vc poderá controlar as transações ou no caso de usar ClientDataSet, deixar que ele faça isso para vc, mas isso não o impede de também controlá-las mesmo usando o ClientDataSet.

Se vc for utiliza os componentes (TDataSetProvider + TClientDataSet + TDataSource), não precisará ter muita preocupação com as transações pq a Midas cuidará disso para vc. Se vc não conhece ou nunca trabalhou com ClientDataSet dê uma pesquisada, aqui memso no forum tem muita coisa, tópicos falando sobre ApplyUpdate e como o ApplyUpdate não levanta exceptions, veja algo sobre o OnReconcilieError, onde vc poderá saber se houve algum erro.
Exemplo:
with CDS1 do
begin
  Append;
  .... 
  Post;
end;
If ApplyUpdates(0)> 0 then
  ShowMessage('Houve um erro ao tentar gravar o registro!')
else
  ShowMessage('Registro gravado com sucesso!'); 


Controlando as transações explicítamente.
var
  Trans: TTransactionDesc;
begin
  with CDS1 do
  begin
    Append;
    ...
    Post;
    Trans.TransactionID:= 1;
    Trans.IsolationLevel:=  xilReadCommitted;
    SQLConnection1.StartTransaction(Trans);
    if  ApplyUpdates(0) = 0 then
      SQLConnection1.Commit(Trans)
    else SQLConnection1.Rollback(Trans);
  end; 


Dependendo da versão do Delphi q vc estiver usando, se for XE2 por exemplo, o DBX4 tem algumas mudanças e melhorias.
Declare no User Data.DBXCommon
var
  Trans: TDBXTransaction;
begin
   Trans := SQLConnection1.BeginTransaction;
   try
    with CDS1 do
    begin
      Append;
      ...
      Post;
    end;
    If CDS1.ApplyUpdates(0) = 0 then
    SQLConnection1.CommitFreeAndNil(Trans); 
    ShowMessage('Os Dados foram gravados com sucesso!');
   Finally
    SQLConnection1.RollbackFreeAndNil(Trans);
   end; 
end;

Algo mais ou menos como descrito acima, assim vc tem controle sobre as transações.

Para maiores informações busque aqui no fórum ou post suas dúvidas, tentaremos ajudá-lo.

Boa sorte e bons códigos.
Responder

Mais Posts

14/02/2013

Volmir Santos

Essa é que é a minha duvida pois nao estou trabalhando com esta estrutura(TDataSetProvider + TClientDataSet + TDataSource)
Estou passando os dados por parametro e uso o TSQLQuerry
Algo tipo:

{Aqui nao sei se Preciso iniciar uma Transacao}
TsqlQuery.sql.clear;
TsqlQuery.sql.add('Insert Into Teste (codigo, nome)Values(:codigo, :nome)');
TsqlQuery.params[0].asinteger:=1;
TsqlQuery.params[1].asString :='Nome';
TsqlQuery.ExecSQL;
{Aqui nao sei se Preciso Commitar a Transacao}

Responder
Essa é que é a minha duvida pois nao estou trabalhando com esta estrutura(TDataSetProvider + TClientDataSet + TDataSource)
Estou passando os dados por parametro e uso o TSQLQuerry
Algo tipo:

{Aqui nao sei se Preciso iniciar uma Transacao}
TsqlQuery.sql.clear;
TsqlQuery.sql.add('Insert Into Teste (codigo, nome)Values(:codigo, :nome)');
TsqlQuery.params[0].asinteger:=1;
TsqlQuery.params[1].asString :='Nome';
TsqlQuery.ExecSQL;
{Aqui nao sei se Preciso Commitar a Transacao}



Ficaria algo mais ou menos assim.


Transacao := SQLConnectio.BeginTransaction; // Inicia a transação

TsqlQuery.Close;
TsqlQuery.sql.clear;
TsqlQuery.sql.add('Insert Into Teste (codigo, nome)Values(:codigo, :nome)');
TsqlQuery.params[0].asinteger:=1;
TsqlQuery.params[1].asString :='Nome';
try
TsqlQuery.ExecSQL;
SQLConnection1.CommitFreeAndNil(Transacao) //Commita a transação
except
    On E: Exception do
    begin
      SQLConnection1.RollbackFreeAndNil(Transacao); // Se houver algum erro, rollback
      ShowMessage('Houve um erro '+ #13 + E.Message);
    end;
end;
...


Boa sorte e bons códigos!
Responder

14/02/2013

Volmir Santos

Ok
Obrigado pelas dicas vou testar
Responder
Ok
Obrigado pelas dicas vou testar


OK! Teste e retorne com o resultado, se precisar de mais ajuda, estamos aqui para tentar ajudar.

Boa sorte e bons códigos!
Responder

15/02/2013

Marco Salles

Blz martins ? Vc é o Martins do velho Forum Clube delphi ???

Então vc faz mais ou menos assim

Transacao := SQLConnectio.BeginTransaction; // Inicia a transação

TsqlQuery.Close;
TsqlQuery.sql.clear;
TsqlQuery.sql.add('Insert Into Teste (codigo, nome)Values(:codigo, :nome)');
TsqlQuery.params[0].asinteger:=1;
TsqlQuery.params[1].asString :='Nome';
try
TsqlQuery.ExecSQL;
SQLConnection1.CommitFreeAndNil(Transacao) //Commita a transação
except
On E: Exception do
begin
SQLConnection1.RollbackFreeAndNil(Transacao); // Se houver algum erro, rollback
ShowMessage('Houve um erro '+ #13 + E.Message);
end;
end;
...

eu faria assim tb so que eu utilizaria

SQLConnection1.RollbackIncompleteFreeAndNil(Transacao); e a estrutura colocaria dentro do try Finallky

try
TsqlQuery.ExecSQL; // deu certo comita deu errrado Finnaly
SQLConnection1.CommitFreeAndNil(Transacao) //Commita a transação
ShowMessage('Dados Salvos com sucesso !!!');
finally
QLConnection1.RollbackIncompleteFreeAndNil(Transacao);//dando certo ou dando errado o método é capaz de dar Roolbak uu
desconsiderar caso ja tenha dado o Commit

Qual a diferença aos meus olhos . Na prática os dois irão funcionar , mas devemos sempre programar para a Regra e raramente para a exceção ... O Programa deve ter muito mais try finally e pouquissimos try excpet ( conceitualmente é
como se a gente soubesse que vai pode falhar e não fizemos nada para evitar a falha a não ser apresenta-la .. Acredito que
o surgimento do RollbackIncompleteFreeAndNil venha a dar este aporte conceitual além de levantar possiveis exceçoes
quando se dar um SQLConnection1.RollbackFreeAndNil(Transacao); de uma transação que por alguma razão não exista , entre outras coisas mais

[]sds e é so uma opinião sem entrar em conflito com o que vc corretamente colocou . Abraços
Responder
Olá Marco Salles, seja bem vindo ao tópico. Tudo bem com vc meu amigo? Sim sou o Martins do bom e velho fórum Clube Delphi, estamos de volta, rsrsrsrs.

Marco, quanto ao código que vc postou.
try
TsqlQuery.ExecSQL; // deu certo comita deu errrado Finnaly
SQLConnection1.CommitFreeAndNil(Transacao) //Commita a transação
ShowMessage('Dados Salvos com sucesso !!!');
finally
QLConnection1.RollbackIncompleteFreeAndNil(Transacao);//dando certo ou dando errado o método é capaz de dar Roolbak uu
desconsiderar caso ja tenha dado o Commit


Concordo com você, sempre tentando mostrar um bom caminho, meu amigo, estou sempre q possível acompanhando o [url]http://marcosalles.wordpress.com[/url], Marco ao longo dos estudos com DBX4, tenho visto códigos como os de baixo:
var
  trans: TDbxTransaction;
begin
  trans := SQLConnection1.BeginTransaction;

---------------------------------------------------------------
var
  trans: TDbxTransaction;
begin

   Trans := SQLConnection1.BeginTransaction(TDBXIsolations.ReadCommitted);
  try
...

Informando o isolamento, qual a diferença na prática entre essas duas instruções?

Quanto ao bloco Try Finally End no lugar d Try Except End, usando o método RollbackIncompleteFreeAndNil, é bem interessante mesmo.


Boa sorte e bons códigos!
Responder

15/02/2013

Marco Salles


Olá Marco Salles, seja bem vindo ao tópico. Tudo bem com vc meu amigo? Sim sou o Martins do bom e velho fórum Clube Delphi, estamos de volta, rsrsrsrs.


Tudo bem ... quanto tempo . a fila anda né

Concordo com você, sempre tentando mostrar um bom caminho, meu amigo, estou sempre q possível acompanhando o http://marcosalles.wordpress.com,


Uma satisfação te-lo comoconvidado noblog . Infelismente nunca recebi um alô seu . Nen pensei que pudesse ler as bobagens
A ultima que escrevi foi ontem e fala de DbXreader

http://marcosalles.wordpress.com/2013/02/14/definir-em-rumtime-ou-passar-como-parametro-o-caminho-do-banco-em-datasnap-dbxreader-dbx4/

dois minutos so para Leitura ( não gasta mais , pouco código e muita conversa . Mas ate hj não vi algo similar a respeito
sobre como definir em rumtime utilizando o Dbxreader

Marco ao longo dos estudos com DBX4, tenho visto códigos como os de baixo:
#Código


var
trans: TDbxTransaction;
begin
trans := SQLConnection1.BeginTransaction;

---------------------------------------------------------------
var
trans: TDbxTransaction;
begin

Trans := SQLConnection1.BeginTransaction(TDBXIsolations.ReadCommitted);
try
...


Informando o isolamento, qual a diferença na prática entre essas duas instruções?


O Delphi é RAD amigo .. E a instrução SQLConnection1.BeginTransaction é mais RAD do que a instrução SQLConnection1.BeginTransaction(TDBXIsolations.ReadCommitted) ... Simples assim Mesmo

Sobre isto ai um detalhe importante . Tem mais duas formas (Talves esta fosse de fato uma dúvida)


 tr:=SQLConnection1.DBXConnection.BeginTransaction(TDBXIsolations.ReadCommitted); 

ou

 tr:=SQLConnection1.DBXConnection.BeginTransaction;


Essas duas formas estão erradas ... Ja as utilizei , porém sempre deu erro de Invalid Transactional Object

Infelismente quando a tecnologia é nova a gente procura artigos . E se esses artigos nos orientam de forma equivocada
nos levamos á frente o erro ... Pq não sedeve utilizar essas duas formas anteriores ???? Porque
DBXConnection é uma interface para o objeto dbExpress subjacente para uma conexão de banco de dados

Em outras palavras vc deve utilizar nos objetos FConnetion:TDBXConnection e não nos Objetos da classe TSQLConnection.

Em outras palavras , isto é Válido


var
trans: TDbxTransaction;
FConnetion:TDBXConnection;
begin
//nivel de isolamento..
tr:=FConnetion.BeginTransaction(TDBXIsolations.ReadCommitted);

ou

tr:=FConnetion.BeginTransaction;


Quanto ao bloco Try Finally End no lugar d Try Except End, usando o método RollbackIncompleteFreeAndNil, é bem interessante mesmo.


È verdade Martins , a partir do delphi 2007 o controle Transactional mudou muito . Agora a transação não é mais inicializa , mas sim Instanciada e quem controla tudo agora é o Objeto da classe TDBXTransaction

[]sds e abraços

Responder

Uma satisfação te-lo como convidado noblog . Infelismente nunca recebi um alô seu . Nen pensei que pudesse ler as bobagens
A ultima que escrevi foi ontem e fala de DbXreader

http://marcosalles.wordpress.com/2013/02/14/definir-em-rumtime-ou-passar-como-parametro-o-caminho-do-banco-em-datasnap-dbxreader-dbx4/

dois minutos so para Leitura ( não gasta mais , pouco código e muita conversa . Mas ate hj não vi algo similar a respeito
sobre como definir em rumtime utilizando o Dbxreader


Acompanho sim, e não tem nenhuma bobagem por lá, sempre muita informação, eu nunca havia comentado, mas a partir de então, sempre q possível deixarei meu comentário sobre o assunto ou tentarei interagir.


O Delphi é RAD amigo .. E a instrução SQLConnection1.BeginTransaction é mais RAD do que a instrução SQLConnection1.BeginTransaction(TDBXIsolations.ReadCommitted) ... Simples assim Mesmo


É verdade, completamente RAD.

 tr:=SQLConnection1.DBXConnection.BeginTransaction(TDBXIsolations.ReadCommitted); 

ou

 tr:=SQLConnection1.DBXConnection.BeginTransaction;


Essas duas formas estão erradas ... Ja as utilizei , porém sempre deu erro de Invalid Transactional Object

Infelismente quando a tecnologia é nova a gente procura artigos . E se esses artigos nos orientam de forma equivocada
nos levamos á frente o erro ... Pq não sedeve utilizar essas duas formas anteriores ???? Porque
DBXConnection é uma interface para o objeto dbExpress subjacente para uma conexão de banco de dados


Foi o que encontrei quando procurei na Embarcadero, documentação sobre o assunto. Lá diz exatamento o que você já fala aqui. DBXConnection é uma interface para o objeto dbExpress subjacente para uma conexão de banco de dados. Normalmente, você não precisa de interagir diretamente com este objeto dbExpress porque todos os seus métodos estão à disposição, direta ou indiretamente, na implementação de TSQLConnection .

var
trans: TDbxTransaction;
FConnetion:TDBXConnection;
begin
//nivel de isolamento..
tr:=FConnetion.BeginTransaction(TDBXIsolations.ReadCommitted);

ou

tr:=FConnetion.BeginTransaction;


Interessante, como um tópico sobre uma dúvida quanto ao controle transacional usando DBX se torna uma aula sobre o assunto, muito bom, os usuários do fórum agradecem. Obrigado meu amigo Marco Salles, abraços.


Boa sorte e bons códigos!
Responder

15/02/2013

Marco Salles

aula foi aquela do NestedDataSet .. eu vc e o Adriano Santos . Lembra ???

[]sds
Responder
aula foi aquela do NestedDataSet .. eu vc e o Adriano Santos . Lembra ???

[]sds


Bons tempos do velho fórum, pessoal nota 10 (Adriano Santos, Nildo, Massuda, Emerson.En, Vinicius2k, Marco Salles, Afarias, Aroldo Zanela, Zoom, Gandalf.nho e outros feras).

Quanto a esse tópico que o amigo está citando é o sobre o uso dos componentes SQLConnection1 -> SQLDataSet1 -> DataSetProvider1 -> ClientDataSet1 -> DataSource1, usando Interbase 6.5, tópico q ficou grande e serviu como fonte de estudo para muitos.


Boa sorte e bons códigos!
Responder

15/02/2013

Marco Salles

Quanto a esse tópico que o amigo está citando é o sobre o uso dos componentes SQLConnection1 -> SQLDataSet1 -> DataSetProvider1 -> ClientDataSet1 -> DataSource1, usando Interbase 6.5, tópico q ficou grande e serviu como fonte de estudo para muitos.


Sim Martins ele mesmo ... Nos na peleja e apredendo juntos . Infelismente na migração muitos tópicos ficarm mau formatados

Bons tempos aqueles

[]sds
Responder
É verdade Marco, pena também que muita gente boa tenha de certa forma se afastado do fórum, espero que assim como eu, eles também retornem.

Parabéns pelo seu blog, tem muita coisa boa lá, muitas informações.

Abraços meu amigo!


Boa sorte e bons códigos!
Responder
Segui a estratégia do uso do RollbackIncompleteFreeAndNil ao invés do RollbackFreeAndNil conforme citado acima.<br />
http://docwiki.embarcadero.com/Libraries/Tokyo/en/Data.SqlExpr.TSQLConnection.RollbackIncompleteFreeAndNil<br />
<br />
No entanto mantive também que se mostra necessário em algumas situações: BeginTransaction(TDBXIsolations.ReadCommitted)<br />
<br />
Meu relato ocorre com a versão XE4 entanto espero muito que tais problemas não ocorram em novas versões rs<br />
<br />
Abraço.<br />
<br />
Responder
×
+1 DevUP
Acesso diário, +1 DevUP
Parabéns, você está investindo na sua carreira