Você está na página 1de 18

Programao Cliente/Servidor

(Parte I)

por: Flvio Lamberti

A programao Cliente/Servidor envolve vrios conceitos, os quais, partem da escolha do banco de dados a
ser acessado, o qual, obrigatoriamente, deve ser um SGBD (Sistema Gerenciador de Banco de Dados
Interbase, SQL Server, Oracle e outros). O simples fato de se utilizar um banco de dados Local (Access,
Paradox, Dbase e outros) tira o ttulo de Cliente/Servidor de um sistema.

O SGBD imprescindvel pelo simples fato do mesmo ter a capacidade de processamento do lado Servidor,
isto , todas as requisies de servios feitas a este banco de dados sero processadas no servidor de banco
de dados e no na estao que fez a requisio, que o que acontece com os bancos de dados Locais, pois
estes servem apenas para armazenamento de informaes. Alm desta vantagem os SGBDs tem outras
caractersticas peculiares a eles, mas este no o enfoque desta matria, sendo assim, vamos adiante.

O esquema abaixo representa um acesso a um SGBD na maneira mais antiga, onde necessitamos de uma
Middleware (camada intermediria de acesso BDE, ODBC, etc...) para o acesso a este banco de dados.
Mesmo sendo uma maneira antiga de acesso algumas empresas ainda mantm esta metodologia de trabalho
por pura falta de tempo ou preguia de converter os sistemas, pois a tecnologia que substituiria esta j se
encontra disponvel no mercado a bastante tempo.

Iremos analisar agora o que precisamos em nosso sistema para que tal esquema no perca suas
caractersticas de Cliente/Servidor.
Para comear no podemos se quer pensar em utilizar um objeto TTable, j que o mesmo foi criado
especificamente para acessos a bancos de dados Locais. Sua engenharia de acesso faz com que a
Middleware seja a responsvel pelo processamento das solicitaes de servios feitas ao servidor, no
utilizando assim os recursos do servidor.

Ento utilizaremos o objeto TQuery, este sim desenvolvido para acessos a SGBDs. O objeto TQuery possui
uma propriedade chamada SQL na qual definimos uma instruo, em linguagem SQL, para acesso ao SGBD o
qual tem a capacidade de interpretao desta linguagem, fazendo assim com que o sistema fique mais rpido
em seu processamento e flexvel em seu desenvolvimento.

Mas, este objeto retorna um pacote de dados Read-Only (somente para leitura), no suprindo ento as
necessidades de manipulao de dados (incluso, alterao e excluso), servindo somente para consultas. Isto
no bem verdade, pois um TQuery pode sim fazer manipulao de dados.

Ns temos a opo de habilitar a propriedade RequestLive do objeto o que no recomendado, pois isto far
com que o objeto TQuery trabalhe como se fosse um TTable, isto , ficando dependente da Middleware.

Partiremos ento para segunda opo e que a mais aconselhada. J que o SGBD tem a capacidade de
interpretao de instrues em linguagem SQL ideal que se utilize deste benefcio para uma melhor
performance de nosso sistema. Para tanto precisaremos de um outro objeto do tipo TUpdateSQL. O nosso
objeto TQuery dever ser ligado a este objeto pela propriedade UpdateObject.

Aps os dois estarem conectados devemos especificar as instrues de incluso, alterao e excluso em
linguagem SQL dentro do objeto TUpdateSQL, atravs das propriedades DeleteSQL, InsertSQL e
ModifySQL. Para os que no possuem conhecimentos de linguagem SQL para tanto e para aqueles
preguiosos assim como eu, temos ainda uma opo mais fcil para tal tarefa que se inicia por darmos um
duplo-click no objeto TUpdateSQL que quando se abrir uma caixa de dilogo, nesta percebemos duas
pastas : Options e SQL. Na pasta Options temos um combobox onde ser exibido o nome da tabela a qual o
objeto TQuery est acessando (isto definido a partir da instruo SQL do TQuery ). Abaixo deste combobox
temos alguns botes :

GetTableFields o qual geralmente no utilizado pois os campos da tabela so automaticamente


relacionados;

DataSetDefaults o qual desfaz todas as alteraes realizadas nesta pasta;

SelectPrimaryKeys o qual define o(s) campo(s) chave da tabela de acordo com as especificaes
da mesma no banco de dados e

GenerateSQL o qual ir gerar automaticamente as instrues de Insert, Delete e Update em


linguagem SQL, as quais aparecero na pasta SQL.

Caso o programador queira e tenha o conhecimento necessrio para tanto, ele pode alterar estas instrues,
mas no necessrio, pois as mesmas funcionam como so geradas.
Na pasta Options ainda temos dois listboxs onde so exibidos, no da esquerda (KeyFields) o(s) campo(s)
chave da tabela e no da direita (UpdateFields) os campos que tero seus valores alterados, includos e/ou
excludos pelas instrues em linguagem SQL.

Aps estes procedimentos, que , no momento da leitura parecero demorados, porm na prtica so muito
simples, o nosso TQuery est quase pronto para ser utilizado para manipulao de dados faltando apenas um
passo mnimo mas de extrema importncia, sem o qual no funcionar.

Basta agora habilitar a propriedade CachedUpdates do TQuery. Esta propriedade faz com que todas as
alteraes (incluso, alterao ou excluso) feitas nos dados sejam armazenadas na memria da mquina
cliente (estao de trabalho), j que isto tambm faz parte do modelo Cliente/Servidor de desenvolvimento de
sistemas. Isto mesmo, o acesso aos dados ou o envio das alteraes realizadas nos mesmos para o banco de
dados no modelo Cliente/Servidor no devem ser realizadas simultaneamente, isto , o acesso ao banco de
dados deve ser minimizado ao mximo. Os dados s devem ser enviados ao servidor quando os mesmos j
estiverem totalmente prontos para tanto, devidamente alterados e condicionados pelas regras que regem o
negcio do sistema, para evitar trfego desnecessrio de dados pela rede e processamentos que gerem erros
de tratamento no SGBD, mantendo assim o servidor sempre disponvel para os demais acessos.

Agora sim seu TQuery est funcionando a toda carga. Consultando, alterando, incuindo e excluindo dados.

E a maneira com que o cdigo ser gerado para isso ? Ser o mesmo cdigo que voc usaria com uma TTable:
Append, Edit, Delete, Post, Cancel. A nica diferena que ns estamos trabalhando com os dados em
memria e, em algum momento, estes dados devero ser enviados ao servidor, para isso basta aplicar um
mtodo ApplyUpdates no objeto TQuery. O momento ideal para isto depender do seu negcio, geralmente
isto realizado aps cada post ou delete.

OBS.: As manipulaes dos dados sero feitas atravs do objeto TQuery, j que ele o responsvel pela
persistncia dos dados em memria. Ento os mtodos relacionados acima dizem respeito a este objeto e no
ao TUpdateSQL.

importante enfatizar que os conceitos Clietne/Servidor no param por a, existe tambm a questo do
controle de transaes no banco de dados, realizado, neste caso, pelo objeto TDatabase, atravs dos mtodos
StartTransaction (incio de transao), Commit (confirmao de transao) e Rollback (Cancelamento de
transao). Uma transao deve ser iniciada sempre antes de se enviar os dados para o SGBD e a
confirmao logo aps este envio.

Para um melhor entendimento destas transaes no SGBD, leia a matria sobre Introduo Bancos de
Dados, tambm escrita por mim.

Quaisquer dvidas sobre esta matria estarei disponvel para esclarecimentos atravs do email
lambertidgdt@aol.com.
Programao Cliente/Servidor

(Parte II)

por Flvio Lamberti

Na primeira parte deste artigo vimos um modelo antigo de desenvolvimento com tecnologia
Cliente/Servidor, o que equivaleria ao desenvolvimento na verso 5.0 do Delphi ou anterior.

A partir de agora iremos utilizar os recursos disponibilizados nas verses 6.0 e posteriores
do Delphi, mas precisamente na verso 7.0, a que a mais atual, j que na verso 8.0 foi
implementada a tecnologia .NET, a qual no se encontra 100% estvel.

Vocs iro reparar que no existem diferenas no que diz respeito aos conceitos
Cliente/Servidor e na prtica tambm no ser difcil de se desenvolver, j que a arquitetura
de desenvolvimento Cliente/Servidor se mantm a mesma, com alguns objetos diferentes.

No modelo acima podemos rever o esquema de conexo ao banco de dados, utilizado no


artigo anterior, o que envolve Um SGBD, uma Middleware, um objeto TDatabase para o
controle das transaes, um objeto TQuery para a persistncia de dados, um TUpdateSQL
para a complementao de cdigo SQL para a manipulao de dados, e um TDataSource
para a liberao de informaes em modo visual nos TDataControls (objetos de interao
com o usurio) e/ou para relacionamentos entre TDataSets.

A partir de agora nosso esquema de conexo com o banco de dados ir mudar um pouco,
mas no para melhor. Calma no precisa se desesperar, a metodologia ser a mesma, as
nicas coisas que iro mudar a princpio sero os objetos de conexo.

No modo antigo de conexo ns dependamos de uma Middleware, o que nos tomava tempo
na implementao e na manuteno dos nossos sistemas, pelo simples fato de que na
implementao de nossos sistemas na rede, era obrigatria a instalao da camada
intermediria de acesso (Middleware) em todas as estaes da rede, o que nos tomava
muito tempo e, caso acontecesse algum problema nesta (seja por atualizaes de drivers ou
problemas fsicos - usurio) devamos reinstalar a Middleware ou simplesmente copiar o
driver de conexo da mesma.

Agora esta Middleware ser extinta juntamente ao TDatabase, pois entrar em seus
lugares um objeto do tipo TSqlConnection (palheta de objetos dbexpress), o qual, alm de
conter os drivers de acesso a banco de dados, tambm ir fazer o controle das transaes.

E em lugar de utilizarmos um TQuery sendo complementado com um TUpdateSQL iremos


utilizar trs objetos, isso mesmo, trs objetos :

TSQLDataSet responsvel pelo acesso a tabela;

TDataSetProvider responsvel por prover os dados para a persistncia e

TClientDataSet responsvel pela persistncia dos dados.

Resumindo, o nmero de objetos aumenta, porm os benefcios so maiores que o trabalho


que isto ir acarretar no desenvolvimento, pelo simples fato de que, no caso de uma
migrao de seu sistema para um modelo n-tier (multi-camada) de acesso a banco de
dados, o seu sistema no ser alterado em praticamente nada, pois estes sero os mesmos
objetos utilizados para este tipo de desenvolvimento. Estas especificaes sero abordadas
nos artigos de desenvolvimento N-tier e Web.

E o nosso bom e velho objeto TDataSouce permanecer o mesmo de sempre.

Passando para a Prtica

muito simples desenvolver sistemas desta maneira, a primeira coisa que deve ser sabida
para tanto que os objetos citados devero estar sempre no mesmo ambiente, isto , no
mesmo formulrio, sendo utilizado para isto, geralmente um TDataModule, que no passa
de um centralizador de objetos de conexo ao banco de dados.

Configurando o TSQLconnection (palheta de objetos DBExpress)

D um duplo-click no TSQLConnection, e aparecer a tela abaixo :


Nesta tela devemos criar uma conexo ao banco de dados desejado, assim como se era
feito na Middleware de acesso a banco de dados. Para tanto basta clicar no boto com o
sinal de +.
Na tela seguinte, em Driver Name deve-se escolher o driver de acesso correspondente ao
banco de dados o qual se deseja acessar e em Connection Name informaremos o nome
pelo qual esta conexo ser chamada. Ao passar por esta etapa, a tela anterior ser re-
estabelecida para que se proceda as configuraes de acesso ao banco de dados que se
deseja. Tomei como exemplo um driver de acesso ao Interbase, mas isso funcionaria com
quaisquer driver de acesso, porm as configuraes de acesso seriam diferentes, mas a
facilidade de configurao seriam as mesmas.

Nesta tela basta configurar a propriedade Database, no lado esquerdo da tela, onde se
encontram as configuraes de acesso, para que o seu driver passe a acessar o banco
desejado.
OBS.: No caso do driver do Interbase, o nome do arquivo .GDB se precede do caminho
completo (IP:Drive:\caminho\arquivo.gdb).

Para testarmos esta conexo basta clicar no boto Test Connection, que se encontra na
barra de botes desta tela (segundo da direita para a esquerda). Caso ocorra tudo bem
partimos para o prximo passo.

Configurando os Demais Objetos

A configurao dos demais objetos muito simples. Comeando pelo TSQLDataSet


(palheta de objetos DbExpress):

Propriedades

SQLConnection : indicar o TSQLConnection que acabamos de configurar;

CommandText : indicar a instruo SQL que ir acessar a(s) tabela(s) do banco de dados.

TDataSetPrivider (palheta de objetos DataAccess):

Propriedade

DataSet : indicar a qual TSQLDataSet este objeto ir se conectar para prover os dados para
a persistncia.

TClientDataSet (palheta de objetos DataAccess):

Propriedade

ProviderName : indicar a qual TDataSetProvider o mesmo ir se conectar para a recepo


dos dados para persistncia.

TDataSource (palheta de objetos DataAccess):

Propriedade

DataSet : indicar a qual TClientDataSet este estar linkado para a liberao visual dos dados
para interao com o usurio.
OBS.: importante tomar cuidado na hora de conectar o TDataSource ao TClientDataSet,
pois na lista que aparece na propriedade de conexo aparecero tambm os objetos do tipo
TSQLDataSet.Caso a conexo seja feita ao objeto errado o resultado esperado no ser
alcanado. Caso isto acontea revise todas as conexes realizadas.

Pronto, basta conectar seus TDataControls ao seu TDataSource que seu sistema estar
funcionando.

Em relao ao cdigo que ser gerado para a manipulao de dados, no teremos muitas
diferenas. Para ativar a conexo do sistema com o banco de dados, iremos abrir o nosso
objeto TSQLConnection, assim como fazamos com o objeto TDataBase. Para
manipularmos os dados iremos aplicar todos os mtodos que j aplicvamos anteriormente :
Insert, Delete, Update, Post, ApplyUpdates, etc..., sendo que, no a partir de um objeto
TQuery e sim a partir do objeto TCllientDataSet, isto mesmo, o objeto TClientDataSet o
responsvel pela persistncia de dados, ento ser a partir dele que iremos manipular os
dados, aplicando o mtodo de acordo com a operao desejada. No que diz respeito aos
objetos TSQLDataSet e TDataSetProvider, no necessrio que se invoque estes, via
cdigo, em nenhum momento, pois toda operao realizada no TClientDataSet
automaticamente repassada para os objetos de conexo anteriores a ele (TDataSetProvider
e TSQLConnetion), de acordo com a funcionalidade do mtodo invocado.

importante enfatizar que a utilizao dos objetos mencionados neste artigo


expressamente recomendada no s pela preparao para uma possvel migrao de
tecnologia Cliente/Servidor para N-Tier e sim, tambm, pelo fato de que outros objetos
encontrados nas palhetas de acesso a dados podem no funcionar 100%.

Comparando o modelo antigo com o novo


Quaisquer dvidas sobre esta matria estarei disponvel para esclarecimentos atravs do
email lambertidgdt@aol.com.
Programao Cliente/Servidor
(Parte III)

por Flvio Lamberti

Neste artigo veremos como representar um relacionamento existente entre as tabelas do


banco de dados nos datasets do nosso bom e velho Delphi, isto , vamos criar um
relacionamento entre datasets e explorar os benefcios que ele ir nos trazer.

Como de costume nestes artigos, vamos manter um padro, primeiro falando sobre a
programao com query e depois falando sobre os SqlDataSets, DataSetProviders e
ClientDataSets.

Comearemos introduzindo em um data module um objeto Query, partindo da premissa que


j existem as tabelas no banco de dados com os seus respectivos relacionamentos, e as
conexes ao banco de dados devidamente criadas (Alias na BDE e objeto Database
conectado ao mesmo). Iremos renomear esta Query para QryPedidos e conect-la ao
database e, em sua propriedade SQL, iremos adotar a seguinte instruo :

Select Pedidos.* From Pedidos Where Pedidos.Id_Pedido = :parID

Em seguida iremos, como de costume de todos, acredito eu, transformar os campos da


tabela em objetos dentro da QryPedidos (duplo click na Query e dentro do fields editor que
se abrir clique com o boto direito do mouse e escolher a opo add all fields), e por fim
habilitar a propriedade cachedupdates, o que imprescindvel para o funcinamento do
relacionamento. Ao habilitar esta propriedade voc est informando ao DataSet que todas as
alteraes realizadas faro efeito apenas na memria do DataSet e no diretamente no
banco de dados.

O prximo passo colocar no data module um DataSource que ir se chamar DsPedidos e


ser conectado a QryPedidos. Este Datasource servir de ponte entre as duas querys.

Introduza uma outra Query e chame-a de QryItens, conecte ao database, e em sua


propriedade DataSource iniciaremos o relacionamento, indicando o Datasource que est
ligado ao outro DataSet (DsPedidos). A propriedade cahedupdates desta query tambm
deve estar habilitada. O prximo passo indicar a instruo sql de acesso na propriedade
SQL :

Select Itens.* From Itens Where Itens.Id_Pedido = :Id_Pedido

Voc achou estranho esta condio criada na instruo sql ? Deve estar se perguntando :
Se pra colocar um parmetro para filtrar os itens do pedido via cdigo eu no precisaria ter
este trabalho todo ? Ento eu lhe responderei, este parmetro ser automaticamente
alimentado por causa do relacionamento entre as Querys atravs do DataSource, isto ,
sempre que for filtrado um pedido na QryPedidos, automaticamente os itens deste pedido
sero filtrados por conta do relacionamento. Isto no quer dizer que, em uma eventual
manipulao (incluso), os itens sero automaticamente associados ao pedido em questo,
a passagem do nmero do pedido para o item dever ser feito manualmente, isto
geralmente realizado no evento before post da QryItens.
Outro ponto muito importante a ser abordado neste relacionamento ser no momento de se
aplicar, no banco de dados, as alteraes realizadas na memria da mquina cliente, j que
nossa query est trabalhando com cachedupdates habilitado. A rotina abaixo enfatiza
perfeitamente este momento :

QryItens.DataSource := nil;
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;
QryItens.DataSource := DsPedidos;

A primeira linha deste cdigo (QryItens.DataSource := nil;) indica que estamos desabilitando
o relacionamento entre as Querys, porque a Query, quando trabalhando em memria
(cachedupdates = true), se atualiza automaticamente aps o envio das alteraes
(incluses, alteraes e/ou excluses) da memria da Query para o banco de dados.

Por exemplo : Caso eu envie uma incluso para o banco de dados com o relacionamento
ainda vigorando, a QryPedidos se atualizaria automaticamente aps este envio
(QryPedidos .ApplyUpdates;) e, devido ao relacionamento, os itens daquele pedido seriam
retornados para QryItens, isto , no retornaria nenhum registro para a QryItens porque, no
banco de dados, ainda no existe nenhum item cadastrado para o mesmo e a QryItens seria
esvaziada, quer dizer, os registros existentes no momento da incluso seriam substitudos
pelos registros retornados do banco de dados (nenhum), sendo assim perdidos os registros
que o usurio havia cadastrado.

Por este motivo devemos desfazer o relacionamento entre as Querys antes de enviar os
dados para o banco de dados e, aps o envio destes dados, realizar a operao inversa,
refazendo o relacionamento, o que feito na ltima linha do procedimento
(QryItens.DataSource := DsPedidos;).

Continuando a anlise do cdigo apresentado, devemos tambm ressaltar a ordem de envio


dos dados ao banco de dados, pois existe um relacionamento entre estas tabelas no banco
de dados, o que nos obriga a seguir uma sequncia de incluso e excluso de registros.

Em uma incluso devemos enviar primeiro os dados da tabela pedidos (PAI), pois o
relacionamento no banco de dados atravs de uma Foreign-Key (chave-estrangeira) nos diz
que um Item (FILHO) s pode ser gravado relacionando-o a um pedido (PAI) que j exista, e
em uma excluso feito o contrrio, pois este relacionamento tambm diz que um pedido
(PAI) que tem itens (FILHO) relacionados a ele no pode ser excludo, portanto devemos
excluir primeiro da tabela de itens, o que perfeitamente feito na rotina acima.

Agora que terminamos a parte onde explanamos o relacionamento entre Querys irei agora
demonstrar como seria realizado este relacionamento entre os objetos da palheta
DbExpress (Delphi 6, 7), para tanto deveremos ter em nosso data module, alm do objeto
SqlConnection devidamente configurado, um objeto SqlDataSet renomeado para SqlPedidos
e outro renomeado para SqlItens e, em suas propriedades ComandText as mesmas
instrues utilizadas nas querys. A exemplo do relacionamento entre querys o SqlItens
dever estar conectado ao DataSource do SqlPedidos atravs da propriedade DataSource.

At o momento no vimos nenhuma diferena do relacionamento entre querys e o


relacionamento entre os objetos da palheta DbExpress, porm estas diferenas se inicaro
agora ao colocarmos apenas um DataSetProvider em nosso data module, onde o mesmo
ser renomeado para DspPedidos e se conectar ao SqlPedidos, assim como indica o
nome. O SqlItens no precisar de um DataSetPrivider ligado a ele e j j vocs ver o por
qu.

Agora precisamos em nosso data module de um ClientDataSet o qual ser chamado de


CdsPedidos, ligado ao DspPedidos e ter os campos transformados em objetos dentro dele
(duplo click no CdsPedidos, clicar com o boto direito do mouse dentro do fields editor que
se abriu e escolher a opo add all fields). Ao fazer esta ltima operao verificamos que
alm dos campos da tabela de pedidos (que foram selecionados no SqlPedidos) tambm foi
criado um datafield chamado SqlItens, este o prprio SqlItens transformado em um
datafield por conta do relacionamento.

Ento, colocaremos um novo ClientDataSet e o chamaremos de CdsItens, e no


precisaremos o conectar a nenhum DataSetProvider e sim, na propriedade DataSetFields,
escolher o CdsPedidos.SqlItens. Tranforme os campos em objeto dentro do CdsItens e
contemplem as maravilhas do Delphi.

Uma das vantagens do relacionamento entre os SqlDataSets que no precisamos


alimentar o campo de relacionamento no dataset filho. No relacionamento entre querys ns
eramos obrigados, no evento before post da query filho (QryItens), a indicar para o registro
(item) a qual pedido ele pertencia, o que no acontece neste modelo, este preenchimento
automtico. E mais uma vantagem deste modelo que o relacionamento no precisa ser
desfeito em nenhum momento, mesmo na hora da gravao o relacionamento pode ser
mantido que no havero problemas.

O cdigo de confirmao das operaes seria simplesmente assim :

If not (CdsPedidos.State in [dsInsert, dsEdit]) then


begin
While not CdsItens.Eof do CdsItens.Delete;
CdsPedidos.Delete;
end;
CdsItens.ApplyUpdates(0);
CdsPedidos.ApplyUpdates(0);
end;

Onde o mtodo ApplyUpdates se encarrega de levar as alteraes realizadas em memria


para serem realizadas no banco de dados, sendo que este mtodo necessita da passagem
de um parmetro que se refere ao nmero mximo de erros que o mesmo ir suportar
durante a operao. Geralemente passado como parmetro o valor de zero, para que a
operao s seja efetuada quando no ocorrer nenhum erro.
Espero ter sido bastante claro nas esplicaes sobre estes relacionamentos entre DataSets,
e que todos os leitores faam um bom proveito dos conhecimentos obtidos atravs da leitura
deste artigo, E aguardem o prximo artigo que provavelmente ser o ltimo da srie sobre
Programao Cliente/Servidor.

Para os que no conhecem os conceitos de bancos de dados cliente/servidor (SGBD)


aconcelho que leiam a metria sobre este assunto nesta mesma sesso do site.

Quaisquer dvidas sobre esta e outras matria escritas por mim, entrem em contato pelo
email lambertidgdt@aol.com.

Abraos

Flvio Lamberti
Programao Cliente/Servidor

(Parte IV)

por Flvio Lamberti

Continuando a dissertao sobre programao cliente/servidor, abordaremos agora uma


questo muito importante no que diz respeito a manipulao de dados, o Controle de
Transaes. Para tanto necessrio que se conhea os conceitos de banco de dados
relacional (SGBD) no contexto de transaes. Aconselho, aqueles que no possuem este
conhecimento que leiam meu artigo sobre Conceito de Banco de Dados que se encontra
neste site, para um melhor aproveitamento do contedo deste artigo.

Comearemos demonstrando como era feito o controle de transaes 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 esto relacionadas entre s. Analisemos o cdigo
abaixo, dando nfase principalmente a segunda e a penltima linhas, j que o resto do
cdigo 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 cdigo acima ordena ao objeto Database que o mesmo inicie uma
transao no banco de dados, atravs do mtodo StartTransaction e a penltima linha do
cdigo faz com que o mesmo objeto Database finalize a transao iniciada anteriormente
atravs do mtodo Commit.

importante enfatizar que o objeto Database trabalha com apenas uma transao aberta
por vez, no aceitando assim a execuo de dois mtodos StartTransaction
consecutivamente.
Isto far com que os dados sejam agrupadas em uma nica transao no banco de dados,
minimizando os riscos de perda de informaes.

Agora vamos ver como ficaria o mesmo controle de transaes atravs dos objetos da
palheta DbExpress.
A funo do objeto SqlConnection o controle de transaes no banco de dados, alm da
conexo com o mesmo. Repare que o cdigo no ter muitas alteraes de cdigo.

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 mtodo de incio e fim de transaes so os mesmos utilizados com o objeto
Database, sendo que necessrio que se passe um parmetro em sua execuo. Este
parmetro indica qual transao est sendo iniciada e qual est sendo finalizada. Isto
mesmo o objeto SqlConnection aceita o controle mutiplo de transaes, caso voc tenha a
necessidade de trabalhar com mais de uma transao aberta ao mesmo tempo.

No cdigo relacionado acima, a transao que iniciada e finalizada logo a seguir, chamada
de TD, na verdade uma varivel do tipo TtransactionDesc, geralemente declarada no Data
Module de sua aplicao, e configurada no evento OnCreate do mesmo. A configurao
simples, j que a varivel declarada como sendo uma classe, ela automaticamente herda
todas as propriedades, mtodos e eventos desta, sendo assim basta usar o cdigo abaixo:

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

Onde na primeira se identifica a transao atravs de um numrico inteiro e na segunda


propriedade de define o nvel de isolamento da transao. xilReadCommited a melhor
configurao a ser adotada, pois esta configurao faz com que a transao que est sendo
aberta s enchergue os dados que foram comitados no banco de dados at o momento do
incio da mesmo. Os dados que forem comitados aps o incio da transao no sero
enchergados por esta.

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

OBS.: Esta configurao do nvel de isolamento como ReadCommited no utilizado


apenas no objeto SqlConnection, mas tambm no objeto Database em sua propriedade
TransIsolation, porm a mesma no foi abordada anteriormente pois este j o valor padro
da propriedade.

Como sempre, espero ter ajudado, e continuo a disposio para tirar as possveis dvidas
relativas aos artigos por mim redigidos atravs do email lambertidgdt@aol.com, para outras
dvidas quaisquer, acessem o forum do site www.clubedelphi.com.br.
Abraos

Flvio Lamberti