Fórum Delphi x PostgreSQL - Transação encerra após erro #453905
02/09/2013
0
Estamos começando a utilizar o PostgreSQL 9 no Delphi, e estamos passando por algumas dificuldades ao se tratar das transações.
Estamos utilizando o conjunto de datasets UniDAC, mas acredito que este mesmo problema deva ocorrer em outros como Zeos.
O problema é o seguinte:
O PostgreSQL por padrão utiliza "AUTOCOMMIT ON" em suas transações, ou seja, ao executar o "POST" os dados são persistidos no banco de dados automaticamente. Para que isso não ocorra precisamos antes executar um "START TRANSACTION", em seguida executar os Inserts, Updates e Deletes, e no final executar o "COMMIT" ou "ROLLBACK".
Até este ponto tudo bem, dessa forma conseguimos utilizar o banco de dados semelhante ao que utilizamos anteriormente no Oracle, ou seja, os dados só são persistidos no banco após executar o COMMIT explicitamente.
A questão é que: após dar o "START TRANSACTION", se algum erro ocorrer ao executar o "POST" a transação atual é "encerrada" automaticamente, impedindo que seja executado "POST" novamente. Ao tentar dar o "POST" novamente recebemos o erro: "transação atual foi interrompida, comandos ignorados até o fim do bloco de transação"
Isso nos obriga a executar um "ROOLBACK" após o erro, então executar um "START TRANSACTION" novamente, e finalmente estamos aptos a executar o "POST" novamente.
Exemplo de situação:
Imagine que você vai cadastrar um produto, então é executado um "START TRANSACTION" e um "INSERT" no dataset de produto, você começa a inserir os dados, grava o produto com o "POST" e tudo ocorre bem. Em seguida começa a cadastrar as derivações desse produto (tudo na mesma TRANSACTION, sem dar COMMIT), e na hora de dar o "POST" no dataset de derivações ocorre um erro de campo requerido, a partir deste ponto já perdemos a transação atual, não podemos simplesmente preencher o campo requerido e dar "POST" novamente, pois ocorre o erro citado acima, somos obrigados a dar "ROLLBACK" e "START TRANSACTION" novamente, e perder o "POST" que foi executado com sucesso no dataset de produtos.
Gostaria de saber se existe alguma forma de contornar esse problema, pois quando estamos em um formulário grande com vários datasets, não podemos simplesmente dar "ROLLBACK" quando um erro ocorrer, pois com isso perdemos todos os "POST" executados em outros datasets que tiveram sucesso.
Agradeço antecipadamente
Abraços.
Douglas Junior
Curtir tópico
+ 0Posts
03/09/2013
Washington Somensi
Gostei + 0
03/09/2013
Douglas Junior
unit AJUniQuery;
interface
uses
System.SysUtils, System.Classes, Data.DB, MemDS, DBAccess, Uni;
type
TAJUniQuery = class(TUniQuery)
private
{ Private declarations }
procedure StartTransactionIfNotExists;
protected
{ Protected declarations }
public
{ Public declarations }
procedure Post; override;
procedure Delete;
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('AJR Controls', [TAJUniQuery]);
end;
{ TAJUniQuery }
procedure TAJUniQuery.Delete;
begin
StartTransactionIfNotExists;
try
Connection.Savepoint('savepoint_ajuniquery');
inherited;
except
on E: Exception do
begin
Connection.RollbackToSavepoint('savepoint_ajuniquery');
raise;
end;
end;
end;
procedure TAJUniQuery.Post;
begin
StartTransactionIfNotExists;
try
Connection.Savepoint('savepoint_ajuniquery');
inherited;
except
on E: Exception do
begin
Connection.RollbackToSavepoint('savepoint_ajuniquery');
raise;
end;
end;
end;
procedure TAJUniQuery.StartTransactionIfNotExists;
begin
if not Connection.InTransaction then
Connection.StartTransaction;
end;
end.Dessa forma, salvamos o Savepoint antes de executar o POST, e se algum erro ocorrer o Savepoint é restaurando, evitando de perder os processos anteriores que foram executados com sucesso.
Implementamos também um método que inicia uma transação automaticamente caso não existe nenhuma em atividade.
Abraços
Douglas Junior
Gostei + 0
03/09/2013
Alessandro Yamasaki
Gostei + 0
03/09/2013
José
Gostei + 0
03/09/2013
Douglas Junior
Abraços.
Gostei + 0
03/09/2013
José
Obrigado e precisando estamos a disposição para ajudar.
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)