30

Revista the Club Megazine - 11-2002.0211

Embed Size (px)

Citation preview

Page 1: Revista the Club Megazine - 11-2002.0211
Page 2: Revista the Club Megazine - 11-2002.0211

Revista The Club Megazine - 11/2002A utilização, reprodução, apropriação, armazenamento em banco de dados,sob qualquer forma ou meio, de textos, fotos e outras criações intelectuaisem cada publicação da revista “The Club” são terminantemente proibidos

sem autorização escrita dos titulares dos direitos autorais.

Copyright© The Club® 2002

Page 3: Revista the Club Megazine - 11-2002.0211

MeGAZINE 3

Editorial

Editorial

Celso Jefferson PaganelliPresidente - The Club

• Editorial ........................................................ 03

• News ............................................................ 04• GFIX - A caixa de ferramentas do InterBase/Firebird ..... 05

• A Facilidade da Criação de um Componente DataWare .. 08

• Criando um banco de dados (instance) no Oracle 9i...(Parte 1) ....................................... 12

• DataSnap - Parte VI - O Cliente COM+ ....................... 16

• IntraWeb Desenvolvimento Rápido de aplicações Web com Delphi ............................................... 26

• Perguntas & Respostas ....................................... 29

THE CLUBRua Acre, 950 - Avaré - SP - CEP 18.700-260

Informações: (0xx14) 3732-3689Suporte: (0xx14) 3733-1588

Fax: (0xx14) 3732-0987

Internethttp://www.theclub.com.br

Cadastro: [email protected]: [email protected]ções: [email protected]

DúvidasCorrespondência ou fax com dúvidas devem serenviados ao - THE CLUB, indicando "Suporte".

OpiniãoSe você quer dar a sua opinião sobre o clube em

geral, mande a sua correspondência para a seção"Tire sua dúvida".

ReproduçãoA utilização, reprodução, apropriação,

armazenamento em banco de dados, sob qualquerforma ou meio, de textos, fotos e outras criações

intelectuais em cada publicação da Revista“The Club” são terminantemente proibidos sem

autorização escrita dos titulares dos direitosautorais.

Copyright© The Club® 2002

Impressão e acabamento:Impressos Gril - Gril Gráfica e Repr. Ind. Ltda.

Tel.: (0xx14) 3762.1345 - Fax: (0xx14) 3762.1259Rua São Paulo, 447 - Cep 18.740-000

Taquarituba - SPTiragem: 5.000 exemplares

Diretor - Presidente

Celso Jefferson M. Paganelli

Diretor Técnico

Mauro Sant’AnnaColaboradores

Mário Camilo Bohm - Anderson H. Rodrigues

Emerson Facunte - Alexandre Magno

Delphi é marca registrada da BorlandInternational, as demais marcas citadas são

registradas pelos seus respectivos proprietários.

Olá amigo do THE CLUB,

Lançamos este mês o novo site do THE CLUB, que acredito que facilitará aindamais a sua navegação. Nós deixamos a interface mais limpa e intuitiva, além deestarmos lançando também alguns novos serviços. Entre estes, destaca-se a novainterface para consulta ao nosso banco de dados.

Neste banco de dados você encontrará todas as perguntas (com as respostas) que jáforam feitas ao suporte técnico do THE CLUB. Esta será uma ferramenta importanteno auxílio no seu dia-a-dia, onde você encontrará rapidamente suas respostas às maisdiversas questões.

Finalizando, espero que você contribua, enviando seu comentário ou crítica sobre osite, e as novas ferramentas disponíveis.

Até o mês que vem !

[email protected]

Page 4: Revista the Club Megazine - 11-2002.0211

MeGAZINE4

News

O Advantage Replicator propicia aos usuários ADS(Advantage Database Server) poderosa solução para manter ereplicar informações de banco de dados em locais distribuídos oupara equipes de força vendas externas. Adicionalmente,disponibiliza o compartilhamento de informações para toda aempresa, com alta disponibilidade e proteção de “backup” queassegura que os dados corporativos estejam sempre corretos eacessíveis quando mais são necessários.

Alavancando a tecnologia do produto chefe de sincronizaçãoda Extended Systems, XTNDConnect Server, o AdvantageReplicator permite sincronização de dados e/ou “subsets” de dadosde banco de dados através de um ou mais sistemas.

Usando replicação, usuários poderão garantir visãoconsistente de informações corporativas críticas ao negócioatravés de diversas localidades. Fornece ao usuário opção deréplica programada de bases de dados do servidor corporativopara servidores de filiais, bem como infra-estrutura paracomputação móvel e distribuição de aplicações.

Alguns Destaques• Alta Disponibilidade: Propicia acesso aos dados quando são

mais necessários. Por exemplo, Advantage Replication propicia àsfiliais ou cadeias de lojas ambientes habilidade de trocar oucompartilhar dados em diversos níveis durante todas asoperações.

ReNet Tecnologia lança Advantage Replication - Solução para Sincronizaçãode Banco de Dados

Assim, informações de pontos de venda, como estoque, podemser compartilhadas com toda a organização.

• Altamente Distribuído: Permite atualizações, “online” ou“offline”. Por exemplo, o Advantage Replication permite a equipesmóveis de força de vendas, onde os usuários estãofreqüentemente desconectados durante o dia, atualizar as basesde dados automaticamente quando eles se conectam a redecorporativa.

• Backup: Assegura que empresas tenham bases de dadoscríticas aos negócios consistentes.

Por exemplo, onde a largura de banda ou requisitos detransmissão não permitam backup fora de horário defuncionamento, o Advantage Replication propicia a possibilidadede execução de warm backup durante todo o tempo de operação.

Advantage Replication para ADS (via XTNDConnect Server)é a solução perfeita para empresas que procuram:

• Consistência entre diversos servidores de banco de dados.• Suporte para usuários “offline”.• Possibilidade de efetuar warm-backup de sua base dados.Visite www.renet.com.br ou contate-nos para detalhes

adicionais e conhecer o programa de avaliação.

ReNet Tecnologia [email protected].: 11 3872-0423

Page 5: Revista the Club Megazine - 11-2002.0211

MeGAZINE 5

O GFIX é um utilitário de linha de comando que pode serutilizado para realizar uma série de tarefas relacionadas à umbanco de dados InterBase ou Firebird. Estas tarefas em suamaioria podem também ser realizadas pelo IBConsole ou outroutilitário gráfico, por este motivo o GFIX acabou se tornandomais popular em plataformas em que ferramentas gráficas nãoestão presentes, como Linux, HP-UX e NetWare. No entanto,como o gfix lida diretamente com operações administrativasextremamente importantes eu sugiro que sempre você faça estastarefas através dele, visto que já tive alguns problemas aorealizar algumas destas tarefas via utilitário gráfico.

Veremos agora um pouco sobre as tarefas realizadas peloGFIX e como executá-las.

- Restart / Shutdown do banco de dadosAlgumas funções de manutenção de banco só podem ser

realizadas se o banco estiver em “shutdown”. Somente o usuárioSYSDBA e o usuário criador do campo possuem permissão pararealizar esta tarefa.

Opções de Shutdown- Por Conexão : Permite que as conexões existentes terminem

o que estão fazendo, mas impede que novas conexões sejamabertas. O banco receberá “shutdown” quando não houver maisconexões.

gfix -shut -attach 120 theclub_server:c:\iblab.gdb-user sysdba -password masterkey

- Por Transação : Aguarda um commit ou rollback para astransações existentes, mas não permite que novas transaçõessejam abertas. O banco receberá “shutdown” quando não houvermais transações ativas.

gfix -shut -tran 120 theclub_server:c:\iblab.gdb-user sysdba -password masterkey

- Forçar Shutdown : O InterBase aguarda até que nãohajam mais transações pendentes, nem conexões abertas, eentão realiza o shutdown no banco. Diferente das opçõesanteriores, onde o shutdown é cancelado se o timeout expirar,esta opção realiza o “shutdown” no banco quando o tempo acabar.

Se houverem transações pendentes, elas serão canceladas(rollback), e todos os usuários conectados serão desconectados.

No exemplo abaixo e nos anteriores utilizamos um timeout de2 minutos(120 segundos).

gfix -shut -force 120 theclub_server:c:\iblab.gdb-user sysdba -password masterkey

Restart do Banco de DadosPara que usuários possam acessar um banco de dados que

tenha recebido um “shutdown”, você deve reinicializá-lo.

gfix -online theclub_server:c:\iblab.gdb-user sysdba -password masterkey

- SweepO Sweep em um banco de dados InterBase elimina registros

desatualizados ou apagados, isto resulta em um banco maisenxuto e coeso. Em um próximo artigo procurarei falar maissobre a operação de sweep.

Definindo um sweep automático

Através do housekeeping você pode definir quando deveráocorrer um sweep automático. O housekeeping controla istoatravés do intervalo entre Oldest Transaction e Next Transaction.

gfix -h[ousekeeping] 10000theclub_server:c:\iblab.gdb

-user sysdba -password masterkey

Neste exemplo utilizei um housekeeping de 10000. O sweepseria executado por exemplo, quando minha Oldest Transactionfosse 3.100 e minha Next Transaction fosse 13.100, ou emqualquer outro intervalo que representasse 10000.

Você pode obter os valores da Oldest e Next Transactionatravés das estatísticas de banco de dados que são realizadas peloGSTAT.

Executando o sweep manualmentePor uma série de motivos você pode preferir abrir mão do

sweep automático e fazer este trabalho manualmente.

Coluna do Alexandre Magno

GFIXA caixa de ferramentas do InterBase/Firebird

Page 6: Revista the Club Megazine - 11-2002.0211

MeGAZINE6

Coluna do Alexandre Magno

Primeiramente você precisa informar ao seu banco que o sweepserá realizado manualmente.gfix -h[ousekeeping] 0 theclub_server:c:\iblab.gdb-user sysdba -password masterkey

Agora toda vez que você quiser realizar um sweep vocêprecisará fazê-lo manualmente através da instrução mostradaabaixo:

gfix -sweep theclub_server:c:\iblab.gdb-user sysdba -password masterkey

Se você estiver em alguma plataforma UNIX poderá aindaagendar o sweep através do utilitário CRON.

cron theclub_server 10:00 ‘gfix -sweeptheclub_server:c:\iblab.gdb -user sysdba -password masterkey’

- Validação de banco de dadosValidação de banco de dados significa verificar o arquivo de

banco de dados para garantir se os vários tipos de estruturas dedados mantém sua integridade e consistência interna.

Opções de validação de banco de dados-v[alidate]Realiza uma validação de banco de dados e verifica se o banco

de dados tem estruturas corrompidas e páginas que estãoalocadas mas não atribuídas a qualquer estrutura de dados.Alguns processos de validação devem incluir esta opção.

-f[ull]Valida registros individualmente dentro de blocos de páginas,

bem como testa toda a estrutura das páginas. Esta opção forneceum alto grau de segurança se você suspeita de uma corrupção nobanco de dados, mas aumenta consideravelmente o tempo doprocesso de validação.

gfix -v -f theclub_server:c:\iblab.gdb-user sysdba -password masterkey-n[o_update]

Realiza somente alterações que liberam espaço perdido; nãorealiza mudanças em páginas que possuam dados dentro delas.

gfix -v -n theclub_server:c:\iblab.gdb-user sysdba -password masterkey-m[end]

Marca registros corrompidos e indisponíveis, para que estessejam futuramente removidos(por exemplo, durante um backupsubsequente).

gfix -m theclub_server:c:\iblab.gdb-user sysdba -password masterkey-i[gnore]

Ignora erros de checksums.

gfix -v -f -i theclub_server:c:\iblab.gdb-user sysdba -password masterkey

- Recuperação de Transações (Transaction Recovery)Quando você efetiva commit em uma transação que envolva

múltiplos bancos, o InterBase automaticamente realiza umcommit em duas fases (two phase commit). O commit em duasfases garante que as atualizações feitas nesta transação ocorramem todos os bancos envolvidos ou em nenhum deles, com isso osdados nunca serão atualizados parcialmente.

Definição de Transações em LimboNa primeira fase do commit em duas fases, o InterBase

prepara cada banco de dados que receberá um commit atravésdas mudanças feitas em cada subtransação do banco. Umasubtransação é uma parte de uma transação multi-database eenvolve somente um banco de dados. Na segunda fase, oInterBase marca cada subtransação como “commited” na ordemem que foi preparada.

Se algum commit em duas fases falhar durante a segundafase, algumas subtransações são “commited” e outras não. Umcommit em duas fases pode falhar por problemas na rede oucrash no disco de um ou mais bancos de dados indisponíveis. Afalha do commit em duas fases causa transações em limbo, nestemomento o servidor não sabe se estas transações deverão ser“commited” ou “rolledback”.

É possível que alguns registros em um banco de dadosestejam inacessíveis devido sua associação com uma transaçãoque está em estado de limbo.

Para corrigir isto, você deve recuperar a transação utilizandoo GFIX ou o IBConsole. Recuperar uma transação em limbosignifica fazer o “commit” ou “rollback” delas.

Recuperando Transações-l[ist]Lista o ID de cada transação em limbo e indica de que

máquina ela partiu.

gfix -l theclub_server:c:\iblab.gdb-user sysdba -password masterkey-c[ommit] {ID | all}

Realiza o commit na transação especificada pelo ID ou emtodas as transações em limbo caso você indique all.

gfix -c all theclub_server:c:\iblab.gdb-user sysdba -password masterkey-r[ollback] {ID | all}

Realiza o rollback na transação especificada pelo ID ou emtodas as transações em limbo caso você indique all.

gfix -r 11500 theclub_server:c:\iblab.gdb-user sysdba -password masterkey

Page 7: Revista the Club Megazine - 11-2002.0211

MeGAZINE 7

-t[wo_phase] {ID | all}Realiza a recuperação automática em duas fases na

transação especificada pelo ID ou em todas as transações emlimbo caso você indique all.

gfix -two_phase all theclub_server:c:\iblab.gdb-user sysdba -password masterkey- Outras funcionalidades do GFIX-b[uffers] n

Define o padrão de buffers em cache do banco de dados em npáginas.

gfix -b 1000 theclub_server:c:\iblab.gdb-user sysdba -password masterkey-kill

Elimina todos os arquivos de shadows indisponíveis.

gfix -kill theclub_server:c:\iblab.gdb-user sysdba -password masterkey-sql_dialect {1 | 3}

Altera o dialeto utilizado pelo banco.

gfix -sql_dialect 3 theclub_server:c:\iblab.gdb-user sysdba -password masterkey-mode {read_only | read_write}

Realiza o modo de utilização do banco de dados.

gfix -mode read_write theclub_server:c:\iblab.gdb-user sysdba -password masterkey-z

Mostra versão do GFIX e do InterBase utilizado.

Coluna do Alexandre Magno

gfix -z theclub_server :c:\iblab.gdb-user sysdba -password masterkey

- Mensagens de Erro do GFIX• DataBase file name <string> already givenUma opção de linha de comando esta sendo interpretada

como um arquivo de banco de dados porque a opção não estásendo precedida por um hifen(-) ou barra(/). Corrija a sintaxe.

• Invalid switchUma opção de linha de comando não foi reconhecida• Incompatible switch combinationsVocê especificou duas ou mais opções que não trabalham

juntas, ou você especificou uma opção que não trabalha semoutra opção(por exemplo, -full)

• More limbo transactions than fit. Try again.O banco de dados contém mais transações em limbo que o

limite de exibição do GFIX. Execute o commit ou rollback emalgumas transações em limbo, e então tente novamente.

• Numeric value requiredA opção -housekeeping, por exemplo, requer um valor

númerico e não-negativo para definir o intervalo de transaçõespor sweep. Corrija a sintaxe.

• Please retry, specifying <string>Pelo menos uma opção deve ser especificada.• Transaction number or “all” required.Ao especificar -commit, -rollback ou -two_phase, você deve

também especificar o ID da transação ou o argumento all

Sobre o autor

Alexandre Magno ([email protected])é diretor da Argos Tecnologia em Belém do Pará.

Page 8: Revista the Club Megazine - 11-2002.0211

MeGAZINE8

Amigos, um dos recursospouco explorados por nósdesenvolvedores, é a criaçãode componentes ou atémesmo, classes, com oobjetivo de abreviar nossotrabalho.

Neste artigo iremosaprender a construir umcomponente derivado deoutro componente. Comcerteza, ao final deste artigo,a maioria perderá o medo,ou melhor, vai criar corageme tornará parte de seucotidiano, e mais umabarreira será quebrada.

Nosso componenteconsiste em melhorar ainterface de comunicaçãocom o usuário, baseado noobjeto TdbEdit.

Vamos implementar as seguintes melhorias:

. Utilização do ENTER para mudar de campo

. Cor de fundo, ao receber o foco

. Cor padrão, ao perder o foco

. Conversão Maiúscula

. Conversão Minúscula

. Sem conversão

A Facilidade da Criação de umComponente DataWare

Um novo dbEdit cheio de recursos

Este tipo de interface, melhora a integração com o usuário,facilitando a percepção do campo, uma segunda alternativa namudança de campo, além de conversões de strings automáticas.

Agora vamos colocar a mão-na-massa e desenvolver nossocomponente. Através das opções Components/New Component...,teremos uma tela semelhante a figura 1.

Figura 1 Criação de componentes.

Autor: Emerson Facunte.

Delphi

Page 9: Revista the Club Megazine - 11-2002.0211

MeGAZINE 9

Ancestor Type Aqui informamos o ancestral do nosso objeto, ou seja, aquele que herdaremos ascaracterísticas para a construção de um novo componente.Veja o nosso exemplo, onde queremos melhorar as funcionalidades de um TdbEdit, entãodevemos selecionar o ancestral TdbEdit, como ilustra a figura 1.

Class Name Nome da nossa classe. Procure utilizar sempre a tipagem T, no inicio, já que é uma práticacomum do Delphi. Em nosso exemplo, iremos criar a classe TFacDbEdit. Repare nanomenclatura da nossa classe: T, representa type Fac, uma nova classe de componentes denominada Fac(unte) DbEdit, herdado dodbEdit.Veja que isso é apenas uma sugestão, baseada nos padrões sugeridos pela Borland

Pallete Page Paleta onde será instalado o nosso componente. Em nosso caso estaremos criando apaleta Facunte, mas fiquem a vontade de alterar esta referência

Unit FileName Nome da nossa Unit. O Delphi irá criar uma unit com o modelo de criação do componente.Utilize sempre o nome da sua classe, com exceção do type T. Em nosso caso facdbedit.pas

Clique no botão OK

Repare que o Delphi gerou uma unit apropriada para a criaçãode componentes.

unit facdbedit;

interfaceuses Windows, Messages, SysUtils, Classes, Graphics,Controls, Forms, Dialogs, StdCtrls, Mask, DBCtrls;type TFacDbEdit = class(TDBEdit) private { Private declarations } protected { Protected declarations } public { Public declarations } published { Published declarations } end;

procedure Register;implementationprocedure Register;

begin RegisterComponents(‘Facunte’, [TFacDbEdit]);end;end.

Iremos analisar cada seção desta unit,

Na seção type, antes do nome da classe, insira o código quesegue:

TCaseMode = (cmNormal, cmLowerCase, cmUpperCase);

Com isso estamos definindo o tipo CaseMode, com três opções:cmNormal, cmLowerCase (letras minúsculas), e cmUpperCase(letras maiúsculas).

Isto não quer dizer que a rotina já está pronta, apenasestamos criando um tipo que será utilizado por essa rotina.

Agora iremos criar as variáveis que serão utilizadasexclusivamente pela nossa classe, portanto devemos criá-las naseção private.

Insira o código a seguir.

private{ Private declarations }FCase : TEditCharCase;FCaseMode : TCaseMode;FOnEnter : TNotifyEvent;

FOnExit : TNotifyEvent;FOnFocusColor : TColor;FOnNotFocusColor : TColor;FEnterLikeTab : Boolean;

Vamos analisar as variáveis:

Delphi

Page 10: Revista the Club Megazine - 11-2002.0211

MeGAZINE10

FCase Será utilizada para armazenar o tipo de conversão

FCaseMode Será utilizada para apresentar a lista de opções de conversão disponíveis. Repare que amesma é baseada na classe TCaseMode, criada no início da seção type.

FOnEnter Baseada no tipo TNotifyEvent, onde iremos sobrescrever (override), o evento OnEnter doobjeto TdbEdit

FOnExit Semelhante ao FOnEnter, mas para sobrescrever (override) o evento OnExit.

FonFocusColor Baseada no tipo TColor, irá armazenar a cor de fundo do campo, quando o mesmoganha o foco

FOnNotFocusColor O inverso da FonFocusColor

FEnterLikeTab Em determinados campos queremos tirar o recurso do ENTER, então criaremos umapropriedade EnterLikeTab, onde o desenvolvedor poderá alterar no Object Inspector seuvalor (boolean).

Agora vamos declarar as procedures que iremos sobrescrever(override), na seção protected

protected{ Protected declarations }procedure KeyPress(var Key: Char); override;procedure DoEnter; override;procedure DoExit; override;

Repare que estamos utilizando o handle override, já que iremossobrescrever estes métodos.

Na seção public , vamos declarar o método Create.

public{ Public declarations }constructor Create(AOwner : TComponent); override;

Na seção published, publicaremos as propriedades queestarão disponíveis no ObjectInspector, além é claro, via código.

published{ Published declarations }property CharCase : TEditCharCase read FCase;property CaseMode : TCaseMode read FCaseMode

write FCaseMode;property OnEnter : TNotifyEvent read FOnEnter

write FOnEnter;property OnExit : TNotifyEvent read FOnExit

write FOnExit;property ColorOnFocus : TColor read FOnFocusColor

write FOnFocusColor;property EnterLikeTab : Boolean read FEnterLikeTab

write FEnterLikeTab;end;

Perceba que estamos utilizando os métodos de leitura egravação em cada property, exceto no CharCase, que iremossubstituir pelo nosso CaseMode.

property CharCase : TEditCharCase read FCase;property CaseMode : TCaseMode read FCaseMode writeFCaseMode;

Repare que na propriedade CaseMode, estamos lendo (obtendoinformações) e gravando (disponibilizando informações) navariável FCaseMode.

As demais seguem o mesmo modelo da CaseMode.

Agora iremos criar nossas procedures na seçãoimplementation.

Primeiramente vamos criar o nosso construtor, onde faremosas definições iniciais do nosso componente.

implementationconstructor TFacDbEdit.Create(AOwner : TComponent);begininherited Create(AOwner);AutoSelect := False;ColorOnFocus := clYellow;FOnNotFocusColor := Color;EnterLikeTab := True;FCase := ecNormal;CaseMode := cmNormal;end;

O código é bastante simples, e a única coisa diferente queestamos fazendo, além de inicializar nossas variáveis, é a

Delphi

Page 11: Revista the Club Megazine - 11-2002.0211

MeGAZINE 11

utilização do inherited Create(AOwner). Aqui estamos herdandoo método Create do componente TdbEdit, e incrementando com onosso código.

Agora vamos criar a rotina KeyPress. Aqui estamosimplementando o tratamento do “pressionamento” de teclas

procedure TFacDbEdit.KeyPress(var Key: Char);varFEditTemp : TCustomForm;begin if (Key = #13) and FEnterLikeTab then begin FEditTemp := GetParentForm(Self); SendMessage(FEditTemp.Handle,

WM_NEXTDLGCTL, 0, 0); Key := #0; exit; end; case CaseMode of cmUpperCase : begin Key := AnsiUpperCase(Key)[1]; end; cmLowerCase : begin Key := AnsiLowerCase(Key)[1]; end; end;inherited KeyPress(Key);end;

Analisando o código temos uma estrutura simples deprogramação.

No bloco que segue, estamos verificando se o usuáriopressionou a tecla Enter, e se aceitamos este comando paramudar de campo. Em caso afirmativo, estamos pegando o Handledo formulário em questão, e enviando uma mensagem paramudar o foco para o próximo objeto.

if (Key = #13) and FEnterLikeTab then begin FEditTemp := GetParentForm(Self); SendMessage(FEditTemp.Handle,

WM_NEXTDLGCTL, 0, 0); Key := #0; exit; end;

Em seguida estamos verificando o valor da propriedadeCaseMode e fazendo a devida conversão.case CaseMode of

cmUpperCase : begin

Key := AnsiUpperCase(Key)[1]; end;

cmLowerCase : beginKey := AnsiLowerCase(Key)[1];

end;end;

E para finalizar, herdamos o método KeyPress do TdbEdit.Agora vamos criar as rotinas DoEnter e DoExit.

procedure TFacDbEdit.DoEnter;beginColor := ColorOnFocus;if Assigned(FOnEnter) thenFOnEnter(Self);end;procedure TFacDbEdit.DoExit;beginColor := FOnNotFocusColor;if Assigned(FOnExit) thenFOnExit(Self);end;

Aqui estamos apenas atribuindo o valor da propriedadeColorOnFocus e FonNotFocusColor ao nosso objeto, de acordo como evento disparado (OnEnter ou OnExit).

Para finalizar o nosso componente, temos a procedureRegister, que irá registrá-lo na paleta Facunte.

procedure Register;beginRegisterComponents(‘Facunte’, [TFacDbEdit]);end;end.

Acredito que todos compreenderam a criação de umcomponente DataWare, e agora é só desfrutar de todo o seupotencial.

Agora é só instalar.Aproveitem para melhorar ainda mais as funcionalidades do

componente.Forte abraço e sucesso à todos.

Delphi

Sobre o autor

Emerson Facunte é Consultor de Tecnologia com diversoslivros publicados, especialista em desenvolvimento deaplicações e-Business utilizando a ferramenta Delphi, baseadoem WebSnap, DataSnap, BizSnap e ISAPI/Apache Modules.

Page 12: Revista the Club Megazine - 11-2002.0211

MeGAZINE12

Autor: Mário Camilo Bohm - Bohm,InteralFone (011) [email protected]

Criando um banco de dados(instance) no Oracle 9i...

(Parte 1)

A partir deste mês, iremos iniciar uma série de matérias arespeito do Oracle 9i, que incorpora uma série de inovações emrelação à versões anteriores...

Mãos à obra !

Vamos nesta matériadiscutir com detalhes a criaçãode uma Instance Oracle, naversão 9.2.x, que é uma dasversões também conhecidacomo Oracle 9i.

Nossa exposição parte dopressuposto que você jáinstalou o software Oracle, masnão criou ainda o banco dedados, o que é altamenterecomendável quando estamosfalando de instalar Oracle. Agrande maioria já nainstalação do software Oracle,cria seu banco de dados(instance), o que além de nãoser necessário é bastante“precipitado”.

Depois de instalar o software Oracle, você pode, através doDatabase Configuration Assistant, criar, modificar ou deletar bancos dedados...

Delphi

Page 13: Revista the Club Megazine - 11-2002.0211

MeGAZINE 13

A primeira opção quevocê deve fazer é se desejacriar, modificar ou deletarum banco de dados, ou aindase deseja gerenciar gabaritos(esta uma inovação dasúltimas versões do DatabaseConfiguration Assistant,muito útil como iremos ver).

• Criar um banco de dadosCria um banco de dados novo• Configurar opções em umbanco de dados Altera algumasconfigurações de um bancode dados já criado• Deletar um banco de dadosExclui um banco de dados etodos os arquivos do sistemaoperacional a ele relacionados• Gerenciar gabaritosModifica os gabaritosexistentes ou cria novosgabaritos.A vantagem de utilizargabaritos é que você podecriar, de forma rápida e fácil,bancos de dados emduplicatas sem ter queespecificar os parâmetrosnecessários mais de uma vez.Ou seja, você cria um modeloe o utiliza para criar umbanco sempre que desejar.Dentro da opção degerenciamento de gabaritos,você pode criar um gabaritoa partir de um outroexistente, pode criar umgabarito com base em umbanco de dados local ouremoto existente.

Para que possamosprosseguir com nossoraciocínio, vamos primeirocriar um banco de dados. (Figura superior).

Ao escolher a opção Criar um Banco de Dados, você deve

escolher entre os gabaritos de banco de dados fornecidos pelaOracle com base em um padrão projetado de interação com ousuário, incluindo: (Figura inferior).

Delphi

Page 14: Revista the Club Megazine - 11-2002.0211

MeGAZINE14

• General PurposeUma variedade de tarefas de banco de dados pode ser executada,desde transações simples até as consultas mais complexas• Online Transaction Processing (OLTP)Cada transação, seja de leitura, gravação ou exclusão de dados dobanco é uma operação relativamente simples que processa umaquantidade pequena de informações, mas existem muitosusuários que executam um número muito grande de transaçõesconcorrentes.• Data Warehousing ou Decision Support System (DSS)Inúmeras consultas complexas são executadas peloprocessamento de grandes quantidades de dados, que exigem altadisponibilidade, tempo de resposta excelente e precisão.Em um ambiente DSS, as consultas variam de um pequenonúmero de registros, até consultas com muitos milhares deregistros em diversas tabelas relacionadas.• New DatabaseUm banco de dados configurado para as suas necessidadesespecíficas.

Na grande maiorias das instalações, a opção General Purposeé altamente recomendável.

Vamos fazê-la em nosso raciocínio. (Figura acima).

A próxima opção nos exigirá a definição de um nome globalpara o banco de dados e um nome de instance (SID). A extensãopadrão global do banco de dados é .world e você pode fornecer essevalor a menos que tenha um nome de domínio estabelecido quequeira usar.

Verifique com seu administrador de rede para saber se existeum domínio específico que você deva usar no lugar da extensão.world. Quando você digita o nome global do banco de dados, omesmo valor, até o “.” será colocado automaticamente no campoSID, como nome da instance.

No nosso exemplo, para o nome global BOHM.ORCL,automaticamente ficou definida a instance como ORCL.

Modo de Servidor Dedicado x Modo de ServidorCompartilhado

A próxima opção a ser feita permite especificar o modo comocada cliente se conectará ao banco de dados. Selecione Modo deServidor Dedicado (que é recomendável na grande maiorias das

Delphi

Page 15: Revista the Club Megazine - 11-2002.0211

MeGAZINE 15

instalações) se o seu banco de dadossuportará um número pequeno deusuários (até 150 usuários porexemplo), ou se os clientespermanecerão conectados por umperíodo grande de tempo.

Nesta opção, para cada conexão aobanco de dados um espaço em memóriaserá alocado exclusivamente paraaquela conexão.

O parâmetro Modo de ServidorCompartilhado, iremos tratarfuturamente.

Por enquanto, faça a opção Modo deServidor Dedicado.

Muito bem!Continuaremos no próximo mês...

Delphi

Page 16: Revista the Club Megazine - 11-2002.0211

MeGAZINE16

IntroduçãoNo artigo anterior criamos nossa aplicação Cliente COM+,

criamos a nossa tela de Login, o formulário principal eimplementamos o método de Login (Login_BD). Também vimos oque é cada componente da Guia DataSnap.

Neste artigo, iremos ver como fazer para criar um RDM eeste conversar com o nosso RDM de Conexão, através doSharedConnection e, criaremos um formulário de CadastroComum com uma regra de negócio para auto-numerar (AutoInc)o código da tabela TAB_ATIVIDADES no Servidor de Aplicação.Mãos a Obra!

Servidor COM+ e Cliente COM+Chegamos a um ponto de desenvolvimento que devemos ter

ambos os projetos abertos para que possamos trabalhar de formaprodutiva e correta. Como já disse no artigo anterior, devemosusar o Project Manager para tal proeza. Então, devemos abrir oDelphi e abrir o arquivo PrjctGrpCOMPlus.bpg que se encontrano diretório C:\DataSnap.

SharedConnection - Múltiplos RDMsAté então, temos no nosso Servidor de Aplicação apenas um

RDM, o RDM de Conexão com o Banco de Dados FireBird.Necessitamos criar para o nosso Cliente COM+, mais um RDM,onde, ele será o nosso RDM de Cadastro Comum.

Devemos criar o RDM para os cadastros comuns, da mesmaforma que criamos o RDM de Conexão.File|New|Other|Multitier e devemos escolher: Transaction DataModule.

CoClass Name= RDMTabelas, Threading Model=Both eTransaction Model=Requires New Transaction. Após issodevemos ter um RDM novinho em folha para trabalharmos. Nãoesquecendo de modificar a propriedade Pooled=True. Nesse RDM

devemos colocar os seguintes componentes: SQLDataSet (GuiadbExpress) e um DataSetProvider (Guia Data Access).

Devemos ter a Figura (1):

DataSnapParte VI - O Cliente COM+

Figura 1: O RDM de Cadastro(s) Comum(ns).

A propriedade name do SQLDataSet deve ser:SQLDtStTabelas e do DataSetProvider: DtStPrvdrTabelas. Apósisso, devemos dar início a ligação entre os RDMs. Vá emFile|Use Unit e ou então ALT+F11 e devemos escolher:RDMConexao. Salve o RDM com o nome de RDMCadTabelas.pase a propriedade name do nosso novo RDM deve ser: RDMTabelas

A Propriedade SQLConnection do nosso SQLDataSet deve serigual a: Server_COMPlus.SQLCnctnBASE, que você visualizaescolhendo a mesma na ComboBox da propriedade. Apropriedade DataSet do DtStPrvdrTabelas deve serSQLDtStTabelas.Também devemos ligar (unir) RDMConexao aRDMTabelas, isto é, devemos selecionar RDMConexao e ALT+F11e escolher RDMCadTabelas. Salve Tudo!

Agora iremos trabalhar na Type Library (View|TypeLibrary). Neste momento já temos a Interface e CoClass criadas,com os seus respectivos nomes: IRDMTabelas, RDMTabelas.Temos de criar uma Interface de ligação entre as duas interfacese as duas CoClass. As duas Interfaces que falo são a dos

Autor: Anderson Haertel Rodrigues

Delphi

Page 17: Revista the Club Megazine - 11-2002.0211

MeGAZINE 17

RDMConexao e RDMTabelas. Clique em New Interface,e indique o nome dessa Interface IChildCadTabelas, apósdevemos criar as duas propriedades, de leitura e escrita, clicandocom o botão direito em cima de IChildCadTabelas: NewProperty|Read-Write, ou então clicar em Figura (2):

Figura 2: Botão indicando onde clicar para criar propriedades.

Indique o nome da propriedade como: RDMCadTabelas, indicandoa 1a com este nome, automaticamente o Delphi coloca o mesmonome na 2a. Fazendo isto, devemos ter uma tela parecida (porenquanto não igual) a Figura (3):

Figura 3 (abaixo): A Type Library mostrando todo o processoenvolvido no parágrafo acima.

Neste momento vamos escolherIChildCadTabelas|RDMCadTabelas (1)- e modificar seu Typepara: IServer_COMPlus *, o seu valor ficará igual a: struct tagIServer_COMPlus *. O Parent Interface de IChildCadTabelasdeve ser igual: IAppServer. Devemos apenas clicar nos nomescitados para selecionarmos a Interface e ou o método.

Após isso, vamos escolher a Interface-IServer_COMPlus que seencontra como a 1a interface do nosso Type Library-

: e vamos incluir uma propriedade doTipo: Read Only- , através de New Property. O seu nomedeve ser: RDMCadTabelas e o seu Type deve ser: IRDMTabelas *,ficando com a declaração igual a: struct tag IRDMTabelas *, epor último, a Interface IRDMTabelas deve ter seu Parent Interfacealterado para: IChildCadTabelas. Ok, agora clique no botão deRefresh implementation , e salve tudo! Agora devemos ter aFigura (3) completa. Observe os traços indicando os seussignificados. E analise um pouco a Type Library.

Todo o processo apresentado acima, também pode servisualizado nos exemplos que acompanham o Delphi, através do

Delphi

Page 18: Revista the Club Megazine - 11-2002.0211

MeGAZINE18

seguinte diretório: ...\{Delphi}\Demos\Midas\SharedConn. Esteexemplo pode lhe orientar a montar a estrutura comSharedConnection.

Após todas as ligações e declarações, se olharmos a unitRDMCadTabelas (Delphi), na seção protected, vamos observarque existe uma nova function e uma nova procedure (métodos),com as seguintes declarações, conforme Listagem 1:

protected class procedure UpdateRegistry

(Register: Boolean; const ClassID, ProgID: string); override;

function Get_RDMCadTabelas: IServer_COMPlus;safecall; procedure Set_RDMCadTabelas

(const Value: IServer_COMPlus); safecall;

Listagem 1: Mostra as declarações da nova Function e danova Procedure.

Após as declarações acima, devemos criar uma variável naseção private do seguinte tipo: FIServer_COMPlus:IServer_COMPlus, onde, IServer_COMPlus é a interface declaradaem RDMConexao. A seção private deve ser igual a listagem 2:

private { Private declarations } FIServer_COMPlus: IServer_COMPlus;

Listagem 2: A seção private da nossa Unit RDMCadTabelas.

Criamos uma variável de referência para a Interface declaradaem RDMConexao.

Na declaração var acima de implementation, devemos ter ocódigo, Listagem 3:

var RDMTabelas: TRDMTabelas; RDMCadTabelasFactory: TComponentFactory;

Listagem 3: A criação da variável que apoiará a ClassFactory (Fabrica de Classe).

Criamos uma variável global que armazena o objeto defábrica de classe.

Vamos agora implementar a função e a procedure declaradasna seção protected, Listagem 4 e 5:

function TRDMTabelas.Get_RDMCadTabelas:IServer_COMPlus;

begin

Result := FIServer_COMPlus;

end;

Listagem 4: A function Get_RDMCatTabelas implementada.

procedure TRDMTabelas.Set_RDMCadTabelas(const Value: IServer_COMPlus);

begin

FIServer_COMPlus := Value;

end;

Listagem 5: A procedure Set_RDMCadTabelas implementada.

A procedure e a function implementada serão usadas pelapropriedade RDMCadTabelas declarada na Type Library, e quetambém pode ser vista em: ServerCOMPlus_TLB

Ainda não terminamos a implementação da Unit. Por últimodevemos modificar o código de initialization, passando ficarigual a Listagem 6:

initialization //TComponentFactory.Create(ComServer, TRDMTabelas, // Class_RDMTabelas, ciMultiInstance, tmBoth);

RDMCadTabelasFactory:=TComponentFactory.Create(ComServer,TRDMTabelas,Class_RDMTabelas, ciMultiInstance,tmBoth);

end.

Listagem 6: A variável criada na listagem 3 entrando emação. Ela receberá todas as informações da Interface e daCoClass do TRDMTabelas.

UFA! Só que ainda nos falta um detalhe. Mas, este detalhe seencontra na Unit RDMConexao.pas. Olhando a seção protectedda Unit veremos as seguintes declarações, listagem 7:

protected class procedure UpdateRegistry

(Register: Boolean; const ClassID,ProgID: string); override;

Delphi

Page 19: Revista the Club Megazine - 11-2002.0211

MeGAZINE 19

function Login_BD(const UserName, PassWord: WideString): WordBool;

safecall; function Get_RDMCadTabelas: IRDMTabelas; safecall;

Listagem 7: A declaração da function

Get_RDMCadTabelas do RDMConexao.

Vamos implementar a function (método)Get_RDMCadTabelas, listagem 8:

function TServer_COMPlus.Get_RDMCadTabelas: IRDMTabelas;

begin

Result :=RDMCadTabelasFactory.CreateCOMObject(nil) as

IRDMTabelas; Result.RDMCadTabelas := Self;

end;

Listagem 8: A implementação da function.

Após isso tudo, vamos executar um Build All no projetoServer e logo após: Run|Register ActiveX Server. Deve aparecera seguinte tela, Figura (4):

Apenas lembre-se que o seu diretório de trabalho é oC:\DataSnap\Servidor. Clique em Ok.

Resumo SharedConnectionAs functions, procedures, variáveis e propriedades que

criamos, são auxiliadoras para as Interfaces, fábricas de classe eCoClass que criamos na Type Library. Num primeiro momento,parece que SharedConnection é complicado, mas, não se deixefrustrar pelo código apresentado. Tudo se baseia em criarreferências de Interfaces e Classes, apontar as mesmas, algunstype casting´s feitos no código e o retorno dos objetos COM (nossoRDM). Volto a lembrar, nosso RDM é um objeto COM!

Cliente COM+Vamos dar início a criação do nosso formulário de cadastro

simples. Vamos criar um novo formulário no Delphi (herdado deTForm) e colocar os seguintes componentes no mesmo:

• 2 Labels;• 2 Buttons;• 2 DBEdits;• 1 SharedConnection;• 1 ConnectionBroker;• 1 DataSource;• 1 ClientDataSet;• 1 DBNavigator;

O mesmo deve se parecer com o seguinte formulário, Figura (5):

Figura 4:O Servidor registrado comSucesso.

Figura 5:O Formulário deCadastro Atividades -Layout Sugerido

Delphi

Page 20: Revista the Club Megazine - 11-2002.0211

MeGAZINE20

Salve o mesmo com o nome de:uFrmAtividade.pas no diretório do projetoCliente. Devemos ligar o DM ao nossoFormulário de Atividade.

ALT+F11 e vamos escolheruDMConexao.

Vamos modificar os nomes de nossoscomponentes do FORM pela boa prática daprogramação e para não perdermos ocostume:

• Nosso FORM com o name=FrmAtividades;• Caption=Cadastro de Atividades;• SharedConnection o name=ShrdCnctnAtividades;• ConnectionBroker o name=CnctnBrkrAtividades;• DataSource o name=DtSrcAtividades;• ClientDataSet o name=ClntDtStAtividades;• Button1 o name=BtnAtualizar;• Button2 o name= BtnCancelar;• DBNavigator o name=DBNvgtrAtividades;• DBEdit1 o name=DBEdtID;• DBEdit2 o name=DBEdtDESCRICAO;

Ok. Feito isso, agora iremos iniciar as ligações doscomponentes acima:

SharedConnection deve ficar igual a Figura (6):

Figura 6: O Object Inspector do SharedConnection.

A propriedade ChildName é o nosso Remote Data Module(RDMCadTabelas). Ele deve aparecer se as ligações feitas naType Library ocorreram com sucesso. A propriedadeParentConnection é o nosso DCOMConnection(DCOMCnctnConexao) que se encontra em DMConexao.pas.

O ConnectionBroker deve ficar igual a Figura (7):

Figura 7: O Object Inspector do ConnectionBroker.

A propriedade Connection é o nosso SharedConnection(ShrdCnctnAtividades).

O nosso DataSource deve estar ligado através da propriedadeDataSet ao nosso ClientDataSet (ClntDtStAtividades).

O ClientDataSet (chamado abreviadamente de CDS) deve serigual a Figura (8):

A propriedade CommandText deve ser igual a: SELECT ID,DESCRICAO FROM TAB_ATIVIDADES, a propriedadeConnectionBroker deve ser igual ao ConnectionBroker(CnctnBrkrAtividades) do Formulário, a propriedadeProviderName deve ser igual ao Provider que se encontra nonosso RDM - DtStPrvdrTabelas.

Para mostrar o(s) Provider(s)disponível(is), você deve escolher o mesmo nocombobox da propriedade.

Os componentes DBEdit´s devem estarligado ao DataSource (DtSrcAtividades) quese encontra no Formulário, e também develigar os DBEdti´s as respectivaspropriedades DataField (ID, DESCRICAO),ligar a propriedade DataSource doDBNavigator igual (DtSrcAtividades).

RemoteServer não necessita ser usado, porque, estamosfazendo a ligação através da propriedade ConnectionBroker.Lembre-se da Abstração da Conexão!

UFA!

Server COM+Mas, para fazermos o nosso exemplo funcionar, necessitamos

ir até a nossa aplicação Servidora para mudarmos alguns

Delphi

Page 21: Revista the Club Megazine - 11-2002.0211

MeGAZINE 21

parâmetros. CTRL+ALT+F11 e vamos escolher o nosso servidorde aplicação ServerCOMPlus.dll. Devemos selecionarRDMCadTabelas e selecionarmos o DataSetProvider (chamadoabreviadamente de DSP) que se encontra no RDM.

Devemos modificar o valor da propriedade Options de: []para: [poPropogateChanges,poAllowCommandText], com esteparâmetro estou indicando ao DataSetProvider que o SQL serápassado do ClientDataSet para o Provider, e é claro, indicandodessa forma para o DataSetProvider que o mesmo deva aceitar oSQL, caso, contrário, acontecerá uma exceção e, as atualizaçõesfeitas no Servidor de Aplicação, serão propagadas para aAplicação Cliente, porque, usamos a opção poPropagateChanges.

Salve Tudo!

A regra de negócio de AutoIncremento no Servidor deAplicação

Nesse momento vamos criar a regra para o auto-incrementodo código da nossa tabela.

Vamos em: View|Type Library, escolheremos a InterfaceIServer_COMPlus, e vamos adicionar um novo método chamado:AutoIncremento, e vamos incluir três parâmetros chamados:Tabela, Coluna com o tipo BSTR e Modifier=[in] e Retorno com otipo Long* e Modifier=[out,retval], devemos ter a Figura (9):

Figura 8: O Object Inspector do ClientDataSet.

Delphi

Page 22: Revista the Club Megazine - 11-2002.0211

MeGAZINE22

Figura 9: A Type Library com o método AutoIncremento eseus parâmetros.

Antes, necessitamos abrir o RDMConexao para colocarmosno RDM um componente SQLDataSet, com seuname=SQLDtStGeral, devemos ter agora o nosso RDM conformea Figura (10):

Figura 10: O novo Layout do RDMConexao.pas -Server_COMPus.

A propriedade SQLConnection do SQLDataSet que acabamosde incluir no RDM, deve ser igual a:SQLCnctnBASE, oSQLConnection que se encontra no próprio RDM. CommandTextdeve ter seu valor vazio mesmo, porque, passaremos o seu valorem tempo de Run-time, dessa forma, podemos aproveitar omesmo para várias finalidades, claro, sempre ligado a SQL de

Banco de Dados. A function AutoIncremento(const Tabela,Coluna: WideString): Integer; safecall; se encontra no mesmoRDM, então, agora vamos implementar a function, Listagem 9:

function TServer_COMPlus.AutoIncremento(constTabela,Coluna: WideString): Integer;begin

with SQLDtStGeral do try

Close;

CommandText := ‘SELECT MAX(‘+Coluna+’)FROM ‘+Tabela;

Open;

if Eof then Result := 1 else Result := Fields[0].AsInteger + 1;

finally

Delphi

Page 23: Revista the Club Megazine - 11-2002.0211

MeGAZINE 23

Close;

end;

end;

Listagem 9: A implementação da Function deAutoIncremento geral para os nossos exemplos.

Temos a regra de AutoIncremento() implementada no nossoServidor de Aplicação, Necessitamos nesse momento, chamar aregra no nosso RDMCadTabelas, para, criarmos oAutoIncremento para a tabela de Atividades (TAB_ATIVIDADES).Com o RDMCadTabelas aberto, selecione o componenteDataSetProvider que possui o nome de: DtStPrvdrTabelas,escolha a guia Events, e vamos escrever o evento:BeforeUpdateRecord(). Esse Evento é o principal evento para asnossas regras de negócios, com ele, podemos modificar os valoresantes que seja realmente executado o ApllyUpdates() do Provider.Ele possui 05 (Cinco) parâmetros: (Sender:TObject;SourceDS:TDataSet; DeltaDS: TCustomClientDataSet;UpdateKind: TUpdateKind; var Applied: Boolean): Onde, mostroo que faz cada um:

• Sender: Tem a mesma função dos parâmetros Sender doseventos do Delphi, nesse caso, Sender é o Provider(DataSetProvider);

• SourceDS: É o DataSet, neste caso, SQLDtStTabelas. É oDataSet de onde os dados são originários.

• DeltaDS : É o ClientDataSet. Ele contém as atualizaçõesvindas do lado Cliente.

• UpdateKind: Recebe o tipo de manutenção que será feita.Você pode com este parâmetro, testar se está sendo Incluído,Alterado e ou Excluído registro(s).

• Applied: Indica ao Provider, que você é o responsável pela(s)atualização(ões).

O Código de implementação do nosso evento é igual aListagem 10:

procedureTRDMTabelas.DtStPrvdrTabelasBeforeUpdateRecord

(Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean);

begin

if UpdateKind = ukInsert then begin

DeltaDS.FieldByName(‘ID’).NewValue := FIServer_COMPlus.AutoIncremento

(‘TAB_ATIVIDADES’,’ID’);

end;

end;

Listagem 10: A implementação da regra de AutoIncremento.

Vimos que é fácil incluir regras e utilizar a mesma. Não énovidade criarmos uma regra, o Login, também é uma regra, eagora com a criação da 2ª regra, estamos nos acostumando acriar regras no servidor de Aplicação.

Na implementação acima, não existe segredo algum, estamospassando para o DeltaDS o novo valor da coluna ID, que nestecaso, é a nossa Chave Primária. FIServer_COMPlus, neste caso,é a referência a interface do RDMConexao.

Salve tudo e registre novamente a DLL ( Run|RegisterActiveX Server).

Cliente COM+Esse vai e vem de um lado para o outro é proposital, para que

você se acostume a trabalhar com o Project Manager, pois,desenvolvendo sistemas MultiCamadas você com certeza andaráde um lado para o outro (hehehe). Novamente CTRL+ALT+F11 edevemos escolher a nossa aplicação Cliente (ClientCOMPlus.exe).

Temos no lado cliente, todas as ligações prontas, mas, só nosfaltam alguns ajustes para podermos incluir, alterar e ou excluirregistros.

O evento OnCreate() do Formulário de Atividades deve ficarigual a listagem 11:

procedure TFrmAtividades.FormCreate(Sender:TObject);begin

ClntDtStAtividades.Open;

end;

Listagem 11: O Evento OnCreate().

Delphi

Page 24: Revista the Club Megazine - 11-2002.0211

MeGAZINE24

Nesse momento estamos apenas abrindo a tabela. O eventoOnClose() devemos ter a listagem 12:

procedure TFrmAtividades.FormClose(Sender: TObject;var Action: TCloseAction);

begin

ClntDtStAtividades.Close;

Action := caFree;

end;

Listagem 12: O Evento OnClose().

Estamos fechando o ClientDataSet e liberando toda amemória alocada pelo formulário.

O evento OnDestroy() devemos ter a seguinte listagem 13:

procedure TFrmAtividades.FormDestroy(Sender: TObject);

begin

FrmAtividades := nil;

end;

Listagem 13: Indicando a referência do formulário para nil.

Nos faltam só “quatro linhas” de código para que tudofuncione como desejado!

No Botão Atualizar - Enviar para o Servidor, devemos ter aseguinte Listagem 14:

procedure TFrmAtividades.BtnAtualizarClick(Sender: TObject);

begin ClntDtStAtividades.ApplyUpdates(0);end;

Listagem 14: Enviando os dados para o Servidor deAplicação.

No Botão Desfazer Dados Locais, devemos ter a seguinteListagem 15:

procedure TFrmAtividades.BtnCancelarClick(Sender: TObject);

begin

if ClntDtStAtividades.ChangeCount > 0 then ClntDtStAtividades.CancelUpdates;

end;

Listagem 15: Desfazendo as alterações Locais.

Note que antes de chamar o método CancelUpdates euverifico realmente se existiu alguma mudança no Delta.

Necessitamos agora, ajudar o Delphi. Na realidade, euacredito que o mesmo é um BUG, e já foi discutido (e muito) nonews da Borland. Particularmente eu esperava que o mesmofosse consertado no Delphi 7... mas, infelizmente não foi!, vamosesperar pelo Delphi 8 (ou será Galileu ;-) ).

No evento BeforePost() do ClientDataSet(ClntDtStAtividades), devemos escrever o seguinte código,Listagem 16:

procedureTFrmAtividades.ClntDtStAtividadesBeforePost

(DataSet: TDataSet);begin

if DataSet.FieldByName(‘ID’).IsNull then DataSet.FieldByName(‘ID’).AsInteger := 0;

end;

Listagem 16: Estamos “ajudando” o Delphi com o códigoacima.

Neste momento, não adianta colocar o valor deRequired=False para a coluna ID do TField do ClientDataSet, oerro ainda acontecerá!

Como disse anteriormente, só faltavam quatro coisas paraque nosso exemplo funcionasse.

O Componente ClientDataSet tem como característicatrabalhar com uma cópia local dos dados. Desta forma, todas asalterações feitas no Cliente - Inclusão, Alteração e ou Exclusão,não são enviadas ao Servidor de Aplicação até que seja chamado ométodo ApplyUpdates(MaxErrors: Integer); Integer , do qual alémde aplicar as modificações locais para o DataSetProvider, temcomo parâmetro o número máximo de erros tolerados peloservidor e como retorno, o número de erros encontrados.

Neste caso, o valor 0, indica que, ao encontrar o primeiro erro,

Delphi

Page 25: Revista the Club Megazine - 11-2002.0211

MeGAZINE 25

o servidor de aplicação abortará o processo de atualização, eenviará o pacote novamente ao ClientDataSet para este decidir oque fazer. O Valor -1, indica que queremos gravar o máximo deregistros possíveis, e se, forem encontrados erros, serão enviadosao CDS apenas os registros onde houveram erros. Se forencontrado erros é executado um RollBack no Servidor. Apropriedade Delta do ClientDataSet é a propriedade querepresenta todos os registros alterados pelo ClientDataSet, amesma é do tipo OLEVariant.

Antes de testarmos realmente o nosso exemplo, acho válidodar um resumo de como funcionam as transações.

TransaçõesNão devemos iniciar a transação quando trabalhamos com

Provider, o processo de (StartTransaction) é iniciado peloResolver. Você não encontrará um componente chamadoResolver, a operação é transparente e a tarefa de atualização dosdados é da classe TCustomResolver . Esse processo é conhecidocomo Resolving. O método ApplyUpdates é que o responsável peloinício do processo chamado (como já citado) Resolving.

Caso não tenham sido encontrados erros no processo, atransação é encerrada (Commit) e, caso ocorram erros, atransação é desfeita (RollBack), e como já citado, os registrosvoltam para o ClientDataSet. Nesse processo todo (Resolving), ointeressante é que, não é utilizado o DataSet, tudo é feito peloProvider! Mas, podemos modificar o mesmo através dapropriedade ResolveToDataSet do DataSetProvider, passando amesma para True.

Testando o nosso exemploFinalmente vamos testar a nossa aplicação. Inclua, Altere,

Exclua registros, e quando decidir enviar os mesmos para oServidor de Aplicação, clique no Botão Atualizar - Enviar para oServidor. Teste também o botão Desfazer Dados Locais.

ConclusãoVimos como utilizar o Componente SharedConnection, que é

de extrema importância para o desenvolvimento de sistemasdistribuídos com o Delphi, assim como o ConnectionBroker.Criamos também nosso 1o exemplo de Cliente COM+ paramanutenção de Dados, onde, dessa vez foi uma atualizaçãosimples, uma tabela.

No próximo artigo, iremos criar mais um RDM e vamos criaruma atualização de Dados Master/Detail!

Qualquer dúvida que surja estou a disposição. Também estoua disposição para troca de idéias.

Sucesso e Saúde a todos! Um Abraço.

Anderson Haertel RodriguesConsultor em desenvolvimento de SistemasClient/Server- MultiCamadas/DataSnap.Oferece treinamentos para empresas em: InterBase,SQL-Server, Delphi e [email protected] [email protected]ópolis - Santa Catarina - Brasil.

Sobre o autor

Delphi

Page 26: Revista the Club Megazine - 11-2002.0211

MeGAZINE26

O IntraWeb é um conjunto de objetos que expandem ascapacidades do Delphi para que você possa desenvolver aplicaçõesWeb como se desenvolvesse aplicações padrão, com formulários.Ele cria formulários Web, adiciona componentes, escreve eventose deixa seu projeto pronto. Em poucas palavras, o software daAToZed, o IntraWeb, permite o desenvolvimento RAD para a Web.Até o Delphi 6, era necessário adquirir esta suite junto aofabricante, porém agora no Delphi 7 a Borland em uma parceriacom a AtoZed Software inclui o IntraWeb junto ao Delphi, dandoao desenvolvedor direito à desenvolver e distribuir aplicações Webconstruídas com o IntraWeb.

Eu fiquei impressionado com os demos do IntraWeb, noentanto, qualquer pessoa pode escrever demos de boa qualidade.Porém, após explorar um pouco mais, eu fiquei realmentemaravilhado quando vi o código fonte dos demos, e comecei aentender porque o IntraWeb é tão especial.

Eu estava esperando ver HTML, JavaScript, módulos Web, eum estado de gerenciamento, como no WebSnap. Ao invés disso oque eu vi foi um código “normal” do Delphi – e isso foi tudo. Se eunão tivesse visto a aplicação rodando em um browser webprimeiro, eu diria que era uma aplicação comum. No entanto, euainda não estava totalmente convencido de que não havia nadamais por trás disso. Então, eu fiz um demo similar ao primeiro,que vou mostrar para você. Eu fiz com que fosse fácil escreveruma aplicação Web, como os demos, para mostrar que oIntraWeb é real.

TestandoPara criar uma nova aplicação IntraWeb, selecione File |

New | Other | IntraWeb | Stand Alone Application. Os projetosStand Alone vem com um servidor http embutido, para que vocênão necessite do Internet Information Server, Apache ouqualquer outro servidor Web. Como projetos, eles são ideais paradepuração, no entanto, eles também podem ser instalados comoWindows Services e desenvolvidos assim. Se um projeto StandAlone está rodando como uma aplicação (e não como um serviço)uma interface de depuração aparecerá. Ela é similar aoWebSnap’s Web Application Debugger, porém muito mais simplese mais conveniente de ser usada.

Todos os projetos do IntraWeb iniciam com duas units: umApplication Form em branco (Web Form), e um ServerController. O Server Controller tem propriedades para ajustes detempo de expiração das sessões, portas e tudo o mais. Uma vezque eu fiz o formulário principal, eu criei alguns controles básicosconforme pode-se ver na figura 1.

IntraWeb

Figura 1: O formulário principal em desenvolvimento

Desenvolvimento Rápido de aplicaçõesWeb com Delphi

Suporte The Club

Delphi

Page 27: Revista the Club Megazine - 11-2002.0211

MeGAZINE 27

Então eu criei o evento mostrado na figura 2 e atribui oevento OnClick para ambos os links. Como você pode ver, isto nãoé complicado. O ponto é que é tudo código Delphi. Esta é amaneira que todas as aplicações IntraWeb aparecem. Então,quando uma aplicação roda, uma interface de depuraçãoaparecerá, como mostra a figura 3.

procedure TformMain.AddLinkClick(Sender: TObject);var  i: Integer;  Dest, Src: TIWListbox;begin   if Sender = AddLink then     begin      Dest := ReserveList;      Src := AvailableList;     end   else     begin      Src := ReserveList;      Dest := AvailableList;     end;   for i := Src.Items.Count - 1 downto 0 do     if Src.Selected[i] then begin      Dest.Items.Add(Src.Items[i]);      Src.Items.Delete(i);     end;  CountLabel.Caption := IntToStr(    AvailableList.Items.Count) + ‘ availabletheatres.’;end;Figura 2: O evento AddLink OnClick

Figura 3: A interface de depurador do IntraWeb

Na interface de depuração, pressione F9 (ou selecione Run |Execute a partir do menu) para iniciar o browserautomaticamente. A figura 4 mostra como a aplicação será vista

Figura 4: A aplicação no Internet Explorer

O que você viu tão longe se refere ao gerenciador de layout, eé isto que o IntraWeb usa por padrão, e se você desenvolver oformulário como uma aplicação Delphi, a página Web será omesmo. O IntraWeb no entanto, tem vários gerenciadores delayout, e você também pode criar o seu próprio. Um dosgerenciadores de layout alternativos é um processador detemplates que permite você atribuir um arquivo HTML para umform criado usando o editor HTML como o Microsoft FrontPageou o Macromedia Dreamweaver. O IntraWeb mescla o formulárioe o arquivo HTML durante o processo de renderização. Istopermite que as pessoas que trabalham com os gráficos projetem ovisual da aplicação para você fazer o apontamento.

Capacidades complexasEmbora o demo seja visto como muito simples, não permita

que isso faça você imaginar que o IntraWeb possa fazer somentecoisas simples. O IntraWeb contém vários demos, porém o meufavorito é o gráfico dinâmico mostrado na figura 5. Este gráficoestá vivo no meu browser. O usuário pode usá-lo com dados sem anecessidade de se requisitar dados do servidor. O usuário podeescolher colunas, linhas e outras funções. As funções suportadasno momento são: Sum, Count, Minimum, Maximum e Average.O gráfico dinâmico é limitado pelas barras e tem outraslimitações. Para opções mais avançadas, o IntraWeb tambémsuporta o TeeChart.

em seu browser, com o Add link adicionado. Eu quase nãoacreditei ! Eu escrevi uma aplicação Web totalmente funcionalem menos de 5 minutos ! Aplicação Web instantânea com umasimples adição de código ! Eu sei que isso soa fácil demais, masisso realmente não foi difícil. Você quer exibir um novoformulário ? Use o método Show. Isto não pode ser mais fácil.

Delphi

Page 28: Revista the Club Megazine - 11-2002.0211

MeGAZINE28

Figura 5: Gráfico dinâmico

O IntraWeb suporta dois modos: Aplicação e Página. Nósestamos olhando o modo Aplicação, que é o melhor para criaraplicações Web. No modo aplicação, o IntraWeb aponta todos osdetalhes para você – gerenciamento de sessão, gerenciamento delink, tudo. Este modo é o mais fácil, de longe, porém o custo dissoé perder um pouco da flexibilidade.

O modo de Página permite que você aponte cada páginaseparadamente, e requer mais trabalho para desenvolver porquevocê deve apontar os estados e links. No entanto, o modo depágina pode ser integrado com o WebBroker ou WebSnap paraconversação. O IntraWeb vem com dois demos de modo depágina.

Desenvolvimento e documentaçãoEstamos discutindo aplicações Web, então o desenvolvimento

é a consideração mais importante que temos. Adicionalmente aodepurador stand-alone que vimos anteriormente, as aplicaçõesIntraWeb podem ser desenvolvidas como se contivessem serviçosWindows, ISAPI DLLs, ou DSOs Apache (somente Windows). Ostipos de desenvolvimento podem ser alterados facilmente pelaalteração de cinco linhas de código (ou menos) e entãorecompilando. Tirando estas poucas linhas de código, asaplicações são iguais.

A documentação é uma parte do IntraWeb. A documentaçãoconsiste de 45 páginas no formato Adobe Acrobat, um arquivo dehelp, e documentação no Web Site. Os arquivos do Adobe Acrobatconsistem do IntraWeb Manual (35 páginas) e do Intro toIntraWeb (10 páginas). O IntraWeb Manual contém dicas,técnicas e outras informações específicas sobre o IntraWeb. Elecontém muita informação útil, no entanto ele necessita ser

expandido, especificamente nas áreas de gerenciamento deforms, modo de página, e criação de componentes customizáveis.AToZed Software prometeu que estes tópicos, e outros, serãoabordados, e updates da documentação serão lançadosperiodicamente.

O IntraWeb também inclui demos que demonstram cadacaracterística do IntraWeb, incluindo acesso a banco de dados,modo de aplicação, modo de página, desenvolvimento de DLLISAPI, desenvolvimento de DSO Apache, templates, integraçãocom o WebBroker, e integração com o WebSnap.

O arquivo de ajuda documenta muitas característicasespecíficas do IntraWeb, porém muitos tópicos passam embranco. Alguns do tópicos em branco, como por exemplo é que umTIWListBox.ItemIndex, é idêntico ao TListBox.ItemIndex nativo do Delphie nos pareceu não ser vital estar na documentação. Não existenenhuma outra documentação, porém, raramente isso énecessário. O desenvolvimento de aplicações IntraWeb é muitoparecido com o desenvolvimento de aplicações Delphi comuns, epenso que isso será um processo natural.

IntegraçãoO IntraWeb também tem um forte programa de integração

com terceiros, e suporte de diversas Empresas. Isto inclui umaintegração com a Bold (http:/www.boldsoft.com) da CentillexSoftware, e suporte para o TeeChart da Steema Software (http://www.teechart.com). A TMS Software (http://www.tmssoftware.com) e a Used-Disks Inc., também fornecemcomponentes add-on com o IntraWeb.

Prós e ContrasO que eu mais gostei do IntraWeb foi:· real desenvolvimento RAD para Web· o conhecimento atual de Delphi pode ser utilizado· não requer experiência de desenvolvimento Web· extremamente flexível· API aberta e flexível· Suporte de terceiros

Talvez a única desvantagem do IntraWeb seja adocumentação, que está para ser aperfeiçoada.

ConclusãoO IntraWeb realmente é fenomenal. Eu pude construir

aplicações Web robustas que demandariam muito mais tempo econhecimento sem o IntraWeb. Ele também permite um controletotal de várias camadas se você quer acessar HTML ouJavaScript. O Delphi torna o desenvolvimento Windows muitomais fácil com a VCL fazendo o acesso as APIs do Windows. OIntraWeb faz o mesmo para o desenvolvimento Web com a suaarquitetura em cima de HTML, JavaScript e Http.

Delphi

Page 29: Revista the Club Megazine - 11-2002.0211

MeGAZINE 29

Perguntas & Respostas

Pergunta: Estou realizando algumas pesquisas em tabelasnum servidor SQL Server 2000. Essas tabelas têm algunscampos tipo bit e tipo char(1). Eu gostaria de exibir nos grids queretornam as pesquisas ao invés de 0 e 1, Sim e Não por exemplo.Porém essas pesquisas se repetem em telas diferentes e eu nãogostaria de ficar declarando campos calculados nos Field’s Editorde cada TAdoQuery e tendo a preocupação de escrever os códigoscorrespondentes. Existe uma maneira de criar esses camposcalculados no próprio SQL e utilizá-los no Delphi?

Resposta: O SQLServer tem suporte a “case” via instruçãoSQL a qual poderá ser utilizada com esta finalidade. Veja abaixoum simples exemplo:

SELECT au_fname, au_lname, CASE state WHEN ‘CA’ THEN ‘California’ WHEN ‘KS’ THEN ‘Kansas’ WHEN ‘TN’ THEN ‘Tennessee’ WHEN ‘OR’ THEN ‘Oregon’ WHEN ‘MI’ THEN ‘Michigan’ WHEN ‘IN’ THEN ‘Indiana’ WHEN ‘MD’ THEN ‘Maryland’ WHEN ‘UT’ THEN ‘Utah’ END AS StateNameFROM pubs.dbo.authorsORDER BY au_lname

Dúvida enviada por Leonardo Cesar Trindade, São Paulo/SP.

Pergunta: Tenho os campos Campo1 e Campo2 do tipoCurrency em um ClientDataSet. Tem como eu criar no RaveReport o resultado

(Campo1 * campo2 / 100) para cada linha de detalhe?

Resposta: Para fazer esse cálculo dentro do Rave Report

iremos utilizar as seguintes configurações:Selecione o componente chamado CalcOp da aba REPORT e

depois clique sobre a banda onde estão sendo impressos os dados;(Esse componente não ficará visível na banda somente é

utilizado para fazer os cálculos entre os campos. Para trabalharcom esse componente selecione-o através do treeview existente aolado do design do relatório.)

Neste componente CalcOp, chamado CalcOp1 iremosconfigurar as seguintes propriedades:

Operator : coMul ß Indica que será feita multiplicaçãoSrc1DataView : indique o dataview que contém o primeiro

campo do cálculoSrc1DataField : indique o primeiro campo do cálculoSrc2DataView : indique o dataview que contem o Segundo

campo do cálculoSrc2DataField : indique o segundo campo do cálculoDisplayFormat : indique a máscara, pode ser ###,##0.00Somente essas propriedades serão ligadas, e neste momento

montamos a fórmula para fazer Campo1 * Campo2.

Agora coloque um segundo componente CalcOp, chamadoCalcOp2, onde completaremos a fórmula dividindo o resulto doCalcOp1 anterior por 100.

No CalcOp2 configure as seguintes propriedades:Operator : coDivSrc1CalcVar : CalcOp1Src2Value : 100,000DestPIVar : vCalculo ß nome da variável criada no relatório

Essa variável vCalculo deve ser criada da seguinte maneira.Selecione o relatório no Treeview, logo abaixo da opção Report

Library, agora na propriedade PIVars escreva o nome da variáveldesejada, no caso vCalculo, e pronto está criada a variável quereceberá o resultado do calculo.

Para finalizar este cálculo, precisamos somente mostrar o

Perguntas &Respostas

Page 30: Revista the Club Megazine - 11-2002.0211

MeGAZINE30

valor que está na variável no relatório e para isso iremos colocarum componente chamado DataText da aba Report. Nestecomponente na propriedade DataField pressione o botão comreticências ( ... ). Agora na tela Data Text Editor selecione nocombo “Post Initialize Variables” a variável que guardamos oresultado do calculo, pressione o botão “Insert_PIVar” e depoispressione o botão Ok. Pronto o resultado do calculo armazenadona variável será impresso no relatório.

Dúvida enviada por Jerrivaldo Costa, Belo Horizonte/MG.

Pergunta: Estou criando um gráfico via DBChart, este éligado no DataSource que por sua vez está ligado a uma IBQuery.

Agora quero alterar as propriedades Dataset, Labels, Bar, X,como faço isso via programação? Já tentei:

DBChart1.Series.Datasource.Dataset := quGrafico; // e nãodeu certo!

Qual é a forma correta?

Resposta: Esta alteração deverá ser feita na “serie” e nãono “DBChart”. Veja abaixo um simples exemplo:

procedure TForm1.SpeedButton1Click(Sender: TObject);begin Series1.DataSource := Table1; Series1.XLabelsSource := ‘Name’; Series1.YValues.ValueSource := ‘Area’;end;

Dúvida enviada por CyberSul - Soluções em Informática,Porto Alegre/RS.

Pergunta: Senhores, na edição do The Club deste mês,sessão “Perguntas & Respostas” foi dada uma dica de comopassar um projeto IntraWeb/IWServerControl para DLL/ISAPI. Aminha dúvida é se é possivel passar também para CGI e em casopositivo de que forma?

Resposta: Infelizmente não. O IntraWeb gera umexecutável quando criamos uma aplicação “StandAllone”, porémeste executável é apenas para ser “rodado” com o servidor doIntraWeb.

Para rodar em um Servidor Web, ele gera somente DLLmesmo.

Dúvida enviada por Eduardo Belo da Silva, Olinda/PE.

Pergunta: Tenho um projeto CLX onde utilizo umcomponente ListBox. Em uma aplicação VCL, bastava euexecutar “ListBox.ItemIndex := 5;” para que posicionasse em umdeterminado item. Testei isso em minha aplicação CLX e nãofuncinou, como resolver?

Resposta: Utilizando o ListBox em aplicação CLX paraposicionar sobre determinado item e mostrá-lo ao usuário, vocêpode utilizar o ItemIndex em conjunto com oMakeCurrentVisible, conforme exemplo abaixo:

procedure TForm1.SpeedButton1Click(Sender: TObject);begin    ListBox1.ItemIndex := 8;    ListBox1.MakeCurrentVisible;end;

Dúvida enviada por Erick Phillipe R. de Almeida, Magé/RJ.

Pergunta: Quando utilizo a seguinte síntaxe no FireBird:SELECT CAST(CODIGO AS CHAR(5))||’-’||NOME AS

DADOS FROM MYTABLEO sistema retorna o campo código concatenado com o campo

nome. Porém eu preciso que o campo código retorne com 6 zeros aesquerda do valor retornado. É possível retornar desta forma?

Resposta: Infelizmente não conhecemos nenhuma UDF quepossibilite acrescer zeros a esquerda de uma string, porém, épossível implementar uma stored procedure com esta finalidade,veja abaixo:CREATE PROCEDURE SP_ZEROS (TOTAL INTEGER, SEMZEROS VARCHAR(10))RETURNS ( COMZEROS VARCHAR(10))ASdeclare variable i integer;beginComZeros = :SemZeros;i = StrLen(ComZeros);while (i < :Total) dobeginComZeros = (‘0’ || ComZeros);i = (i+1);endsuspend;end

Exemplo da chamada:SELECT(SELECT COMZEROS FROM SP_ZEROS(6, A.CODIGO)) || ‘-’|| A.NOMEFROM CADTESTE A

Dúvida enviada por Megasoftware Ltda, Salvador/BA.

Perguntas & Respostas