Transação com dbExpress

Delphi

27/05/2005

Estou trabalhando com Delphi 7 e dbExpress e gostaria de saber como posso isolar 2 transações, ou seja, se tenho 2 forms MDI e são feitas atualizações em cada Form gostaria de tratar uma transação para cada Form pois se precisar chamar o RollBack, deveria ser apenas daquele form em específico.

1) Quando coloco em transação atualmente eu consigo dar uma nova numeração isolando a transação para cada form. Ex.
var
TD: TTransactionDesc;
begin
if Banco.TransactionsSupported then
begin
Randomize;
TD.GlobalID := Random(999999999);
TD.TransactionID := TD.GlobalID;
TD.IsolationLevel := xilREADCOMMITTED;
Banco.StartTransaction(TD);
Result := TD.GlobalID; // Retorna para variavel CodigoTransacao
end;

2) Quando executo um commit posso me referir a qual
transação se refere mencionando o CodigoTransacao recebido no
passo anterior (1)
var
TD: TTransactionDesc;
begin
if Banco.InTransaction then
begin
TD.GlobalID := CodigoTransacao;
TD.TransactionID := CodigoTransacao;
TD.IsolationLevel := xilREADCOMMITTED;
Result := (icdComTra = nil) or (icdComTra.ApplyUpdates(0) = 0);
Banco.Commit(TD);
end;

// Problema
Quando dou um ApplyUpdates(0) Não consigo dizer de qual transação se refere... Como que o Delphi/Firebird saberia distinguir que as atualizações realizadas no Form1 são referentes a um CodigoTransacao e que as atualizações do Form2 são de outro CodigoTransação?


Qualquer ajuda ou sugestão é bem vinda !!! Obrigado !


Mcd

Mcd

Curtidas 0

Melhor post

Vinicius2k

Vinicius2k

27/05/2005

Colega,

Considere o seguinte, inicialmente:

1. O TransactionID é uma variável que seu valor não tem nenhuma influência no SGBD. Ele -- o SGBD -- não toma conhecimento de seu valor. Ele serve unicamente para diferenciação, dentro da própria aplicação, sobre qual transação estão sendo aplicados os métodos, isto porque um mesmo TSQLConnection suporta múltiplas transações concorrentes.

2. Uma transação tem dois pontos: início e fim. Tudo o que está entre estes dois pontos faz parte da mesma transação.
Se vc iniciar a transação ´1´ e executar métodos após seu início, todos estes métodos são dela. Se quiser isolar outros métodos em outra transação terá que iniciar a transação ´2´ e aplicar estes outros métodos, sendo que, após iniciar a transação ´2´ tudo que for executado pertence à ela e o contexto só volta para a ´1´ quando a ´2´ for finalizada.

3. No seu caso específico, se está trabalhando com Firebird, a GlobalID é desnecessária pois só se aplica ao Oracle.

4. Vc não precisa utilizar números randômicos para identificar a transação, basta que vc não inicie a uma transação com a mesma ID que de uma que ainda não foi fechada. Utilize uma numeração conhecida por você em tempo de projeto para que vc possa controlar as transações separadamente.

Em síntese, é o fluxo do programa que determina qual transação está sendo utilizada. Não há como especificar a qual transação pertence cada execução SQL. Não no dbExpress, com uma única conexão.

Eu *suponho* (nunca testei) que em outras camadas, como IBX e FIB+, por exemplo, vc conseguiria o desejado, pois cada DataSet pode ser ligado à componentes ´Transactions´ diferentes e, segundo meu ponto de vista, isoladas as execuções SQL de cada transação.
Para ter o mesmo efeito no DBX, vc precisaria usar TSQLConnections diferentes.

Voltando ao seu caso, vc precisa iniciar a transação imediatamente antes do ApplyUpdates e fechá-la logo após. Então, este ApplyUpdates estará dentro da transação que vc iniciou. É neste ponto que justifica a 4ª consideração que fiz sobre vc não precisar randomizar a ID.

Eu não sei em que momento vc está iniciando a transação, mas esteja certo, de que mantê-las curtas é a prática mais adequada, por isto, creio que a forma para qual vc deve alterar a sua metodologia, além de ser a melhor solução, é a forma ideal.

Em casos excepcionais, vc pode usar o método CloneConnection do TSQLConnection para criar ´clones´ da mesma conexão a fim de isolar, complementamente, execuções SQL.

Espero ter ajudado.
T+


GOSTEI 1
POSTAR