Desenvolvimento - Delphi

Delphi: Programação Cliente/Servidor - parte 4

Continuando a dissertação sobre programação cliente/servidor, abordaremos agora uma questão muito importante no que diz respeito a manipulação de dados, o Controle de Transações.

por Flávio Lamberti



Continuando a dissertação sobre programação cliente/servidor, abordaremos agora uma questão muito importante no que diz respeito a manipulação de dados, o Controle de Transações. Para tanto é necessário que se conheça os conceitos de banco de dados relacional (SGBD) no contexto de transações. Aconselho, à aqueles que não possuem este conhecimento que leiam meu artigo sobre Conceito de Banco de Dados que se encontra neste site, para um melhor aproveitamento do conteúdo deste artigo.

Começaremos demonstrando como era feito o controle de transações se utilizando o objeto Database. Tomemos como exemplo o famoso modelo de banco de dados com uma tabela de pedidos e outra de itens as quais estão relacionadas entre sí. Analisemos o código abaixo, dando ênfase principalmente a segunda e a penúltima linhas, já que o resto do código foi abordado no artigo anterior:

QryItens.DataSource := nil;
DataBase.StartTransaction;
If QryPedidos.State in [dsInsert, dsEdit] then 
begin
QryPedidos .ApplyUpdates;
QryItens.ApplyUpdates;
end
else
begin
While not QryItens.Eof do QryItens .Delete;
QryPedidos.Delete;
QryItens.ApplyUpdates;
QryPedidos .ApplyUpdates;
end;
Database.Commit;
QryItens.DataSource := DsPedidos;

A segunda linha do código acima ordena ao objeto Database que o mesmo inicie uma transação no banco de dados, através do método StartTransaction e a penúltima linha do código faz com que o mesmo objeto Database finalize a transação iniciada anteriormente através do método Commit.

É importante enfatizar que o objeto Database trabalha com apenas uma transação aberta por vez, não aceitando assim a execução de dois métodos StartTransaction consecutivamente. Isto fará com que os dados sejam agrupadas em uma única transação no banco de dados, minimizando os riscos de perda de informações.

Agora vamos ver como ficaria o mesmo controle de transações através dos objetos da palheta DbExpress. A função do objeto SqlConnection o controle de transações no banco de dados, além da conexão com o mesmo. Repare que o código não terá muitas alterações de código.

If not (CdsPedidos.State in [dsInsert, dsEdit]) then
begin
While not CdsItens.Eof do CdsItens.Delete;
CdsPedidos.Delete;
end;
SqlConnection.StartTransaction(TD);
CdsItens.ApplyUpdates(0);
CdsPedidos.ApplyUpdates(0);
SqlConnection.Commit(TD);
end;

Repare que os método de início e fim de transações são os mesmos utilizados com o objeto Database, sendo que é necessário que se passe um parâmetro em sua execução. Este parâmetro indica qual transação está sendo iniciada e qual está sendo finalizada. Isto mesmo o objeto SqlConnection aceita o controle mutiplo de transações, caso você tenha a necessidade de trabalhar com mais de uma transação aberta ao mesmo tempo.

No código relacionado acima, a transação que é iniciada e finalizada logo a seguir, chamada de TD, na verdade uma variável do tipo TtransactionDesc, geralemente declarada no Data Module de sua aplicação, e configurada no evento OnCreate do mesmo. A configuração é simples, já que a variável é declarada como sendo uma classe, ela automaticamente herda todas as propriedades, métodos e eventos desta, sendo assim basta usar o código abaixo:

TD.TransactionId := 1;
TD.IsolationLevel := xilReadCommited;

Onde na primeira se identifica a transação através de um numérico inteiro e na segunda propriedade de define o nível de isolamento da transação. xilReadCommited é a melhor configuração a ser adotada, pois esta configuração faz com que a transação que está sendo aberta só enchergue os dados que foram comitados no banco de dados até o momento do início da mesmo. Os dados que forem comitados após o início da transação não serão enchergados por esta.

Caso seja sua necessidade trabahar com duas transações em aberto ao mesmo tempo onde uma independa da outra, basta criar outra variável do mesmo tipo e configurá-la com o TransactionId = 1, ou com o identificador diferente dos demais.

OBS.: Esta configuração do nível de isolamento como ReadCommited não é utilizado apenas no objeto SqlConnection, mas também no objeto Database em sua propriedade TransIsolation, porém a mesma não foi abordada anteriormente pois este já é o valor padrão da propriedade.

Como sempre, espero ter ajudado, e continuo a disposição para tirar as possíveis dúvidas relativas aos artigos por mim redigidos através do meu email.

Abraços

Flávio Lamberti

Flávio Lamberti

Flávio Lamberti