curso

260
DELPHI6 e tecnologias de bancos de dados 1 DELPHI 6 E tecnologias de bancos de dados

Upload: alexvrd

Post on 01-Dec-2015

226 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Curso

DELPHI6 e tecnologias de bancos de dados

1

DD EE LL PP HH II 66

EE tt ee cc nn oo ll oo gg ii aa ss dd ee bb aa nn cc oo ss dd ee dd aa dd oo ss

Page 2: Curso

DELPHI6 e tecnologias de bancos de dados

2

Esta apostila foi criada recuperando informações de diversas fontes. Porém, algumas merecem sercitadas tanto por sua importância como material de referência, como por terem sido usadasextensivamente na montagem dos textos desta apostila:

• Borland Delphi 5 Developer’s Guide. Editado pela Borland.

• Borland Delphi 6 Developer’s Guide. Editado pela Borland.

• Object Pascal Language Reference. Editado pela Borland.

• Borland Delphi 6 Quick Start. Editado pela Borland.

Diversos trechos destas obras foram traduzidos e adaptados para o contexto desta apostila. Todos osdireitos referentes a estas obras são de propriedade da Borland Corporation.

É proibida a comercialização desta apostila.

Page 3: Curso

DELPHI6 e tecnologias de bancos de dados

3

Delphi 6.0 e tecnologias de bancos de dados

Parte I - Delphi, Kylix e o Object Pascal

CAPÍTULO 1 - VISÃO GERAL ............................................................................................ 15

O que é o Delphi? ............................................................................................................ 16Aplicativos Windows e aplicativos Linux..............................................................................................16Tipos de aplicativos ............................................................................................................................16Suporte a tecnologias.........................................................................................................................17Versões do Delphi...............................................................................................................................18Delphi.NET .........................................................................................................................................18

O que é o Kylix? .............................................................................................................. 19Escolhendo uma linguagem de desenvolvimento................................................................................19Tipos de aplicativos ............................................................................................................................20Suporte a tecnologias.........................................................................................................................20Versões do Kylix .................................................................................................................................21

CAPÍTULO 2 - O AMBIENTE DELPHI ................................................................................. 22

O ambiente Delphi........................................................................................................... 23A Janela Principal ...............................................................................................................................23O Editor de Código (Code Editor).......................................................................................................24O Object Inspector .............................................................................................................................24O Object Treeview..............................................................................................................................25A Palheta de Componentes ................................................................................................................26O Object Repository ...........................................................................................................................27O Project Manager .............................................................................................................................28

Organização do programa ............................................................................................... 29Arquivos fontes pascal........................................................................................................................29Outros arquivos de aplicações ............................................................................................................29Arquivos gerados pelo compilador......................................................................................................30Uma simples aplicação console...........................................................................................................30

Alguns recursos importantes da IDE ................................................................................ 30Encaixe de janelas (Dock) ..................................................................................................................31Preenchimento de classes ..................................................................................................................31Navegação entre seções de interface e implemntation.......................................................................32AppBrowser........................................................................................................................................32TO-DO List..........................................................................................................................................33Code Insight.......................................................................................................................................33

CAPÍTULO 3 – CONHECENDO O OBJECT PASCAL............................................................... 34

Programação orientada a objetos.................................................................................... 35Orientação a objeto............................................................................................................................35

O Object Pascal .............................................................................................................. 36O que é um objeto? ...........................................................................................................................37

Page 4: Curso

DELPHI6 e tecnologias de bancos de dados

4

Classes, objetos e componentes .........................................................................................................37

Programação estruturada e syntax.................................................................................. 38Unidades estruturadas e syntax..........................................................................................................38A seção Interface ...............................................................................................................................39A seção Implementation.....................................................................................................................39A seção Initialization...........................................................................................................................39A seção Finalization ............................................................................................................................40Referências circulares.........................................................................................................................40

Identificadores, diretivas, palavras-chaves ...................................................................... 41Diretivas .............................................................................................................................................41

CAPÍTULO 4 - TIPOS DE DADOS E ESTRUTURAS............................................................... 43

Classificação................................................................................................................... 44Simples...............................................................................................................................................44Tipos subrange...................................................................................................................................44Tipos real ...........................................................................................................................................44Tipos string ........................................................................................................................................45Tipo Boolean ......................................................................................................................................45Tipos estruturados..............................................................................................................................45Conjuntos (sets) .................................................................................................................................46Arrays.................................................................................................................................................46Arrays dinâmicos ................................................................................................................................47Records ..............................................................................................................................................47Tipos variant.......................................................................................................................................48Tipo OleVariant ..................................................................................................................................48

Conversões de tipos ........................................................................................................ 49Conversões implícitas e explícitas .......................................................................................................50

Trabalhando com strings................................................................................................. 50Concatenando strings.........................................................................................................................51Manipulando strings ...........................................................................................................................52Copiando strings.................................................................................................................................52Inserindo strings ................................................................................................................................53Deletando strings ...............................................................................................................................53Formatando strings ............................................................................................................................53Mais sobre strings...............................................................................................................................54

Trabalhando com datas................................................................................................... 54Dias, meses, anos...............................................................................................................................55Interpretando horas ...........................................................................................................................56

CAPÍTULO 5 - PROCEDIMENTOS E FUNÇÕES.................................................................... 58

Procedimentos e funções................................................................................................. 59Diferenciando procedimentos e funções.............................................................................................59

Conhecendo procedimentos e funções .............................................................................. 59Declarações de procedimentos ...........................................................................................................60Declarações de funções......................................................................................................................60Overloading de procedimentos e funções...........................................................................................61Valor padrão de parâmetros...............................................................................................................62

Page 5: Curso

DELPHI6 e tecnologias de bancos de dados

5

CAPÍTULO 6 - OBJETOS E CLASSES .................................................................................. 63

Tipo de Classe (class type ) .............................................................................................. 64Campos de tipos.................................................................................................................................64

TObject e TClass ............................................................................................................. 65

Visibilidade de membros de classes.................................................................................. 66

Campos .......................................................................................................................... 68

Métodos ......................................................................................................................... 68Declarações e implementações de métodos .......................................................................................69

Inherited ........................................................................................................................ 69

Self ................................................................................................................................ 69Tipos de métodos ...............................................................................................................................70Métodos estáticos ...............................................................................................................................70Métodos virtuais .................................................................................................................................71Métodos dinâmicos .............................................................................................................................71

CAPÍTULO 7 - CONHECENDO A VCL E A CLX...................................................................... 72

Bibliotecas de classes no Delphi 6 .................................................................................... 73

Conhecendo a VCL........................................................................................................... 73Classes raízes da VCL .........................................................................................................................74TObject ..............................................................................................................................................74TPersistent .........................................................................................................................................75TComponent.......................................................................................................................................75TControl .............................................................................................................................................76TWinControl .......................................................................................................................................76TGraphicCotrol ...................................................................................................................................76

Classes de manipulação de exceções................................................................................ 77

Conhecendo a CLX........................................................................................................... 78Obtendo compatibilidade entre Delphi e Kylix....................................................................................78Amplo suporte ao desenvolvimento WEB e banco de dados...............................................................79

Diferenças tecnológicas básicas entre a VCL e a CLX......................................................... 79

CAPÍTULO 8 - TAREFAS COMUNS DE PROGRAMAÇÃO ....................................................... 81

Trabalhando com listas de strings.................................................................................... 82As classes Tstrings e TStringList.........................................................................................................82Usando listas de strings com arquivos................................................................................................82Contando strings na lista....................................................................................................................83Acessando uma string em particular ..................................................................................................83Movendo uma string dentro da lista ...................................................................................................83Deletando uma string da lista.............................................................................................................84Copiando uma lista completa de strings.............................................................................................84

Manipulando Exceções .................................................................................................... 84Exceções e o controle de fluxo ...........................................................................................................84Try ... Exception .................................................................................................................................86

Page 6: Curso

DELPHI6 e tecnologias de bancos de dados

6

Que tipo de recursos proteger?..........................................................................................................86

Manipulando classes de exceções .................................................................................... 87Definindo suas próprias exceções.......................................................................................................88

Guardando informações na Registry e em arquivos .ini ..................................................... 89A classe TRegistry ..............................................................................................................................89A classe TIniFile .................................................................................................................................91A classe TRegistryIniFile.....................................................................................................................92

Estudando o objeto TForm .............................................................................................. 92Janelas e formulários no Win32..........................................................................................................92Métodos de acesso e destruição .........................................................................................................93Tipos de formulários...........................................................................................................................95O objeto TFrame ................................................................................................................................95

Construindo a interface com o usuário ............................................................................. 96Action Lists .........................................................................................................................................96Centralizando código com listas de ações...........................................................................................97Executando ações...............................................................................................................................97Atualizando ações...............................................................................................................................98Ações pré-definidas............................................................................................................................98

Desenvolvendo menus..................................................................................................... 98O Menu Designer................................................................................................................................99Menus estilo Windows 2000 e XP........................................................................................................99Outras barras de ferramentas ..........................................................................................................100

Trabalhando com arquivos .............................................................................................101Tipos de arquivos .............................................................................................................................101Usando arquivos texto ......................................................................................................................101Criando um editor de texto funcional ...............................................................................................102Controles de edição de texto ............................................................................................................102

O projeto MemoEdit .......................................................................................................102Inserindo um ActionManager ...........................................................................................................102Desenhando as barras de ferramentas e menus ..............................................................................103Exibindo informações sobre as funcionalidades de MemoEditor .......................................................104Editando textos.................................................................................................................................105Salvando os dados em arquivo .........................................................................................................107Inserindo uma tela de créditos (“About”) .........................................................................................108Inserindo o ícone da aplicação na tela “About” ................................................................................109

Trabalhando com imagens e desenhos ............................................................................114Usando TCanvas como uma superfície de desenho..........................................................................114

Tipos de objetos gráficos................................................................................................114Conhecendo TImage ........................................................................................................................115

Criando um aplicativo de desenho funcional ....................................................................115O projeto do aplicativo .....................................................................................................................115Implementando os recursos de manipulação de arquivos ................................................................116Implementando recursos de trabalho com imagens.........................................................................116Implementando recursos de desenho...............................................................................................116Informações de arquivos ..................................................................................................................116

Técnicas avançadas de trabalho com gráficos .................................................................116Espectros de cores ...........................................................................................................................116

Page 7: Curso

DELPHI6 e tecnologias de bancos de dados

7

Rotacionando imagens .....................................................................................................................117Invertendo imagens .........................................................................................................................117

CAPÍTULO 9 - TECNOLOGIAS DE ACESSO A FONTES DE DADOS........................................119

Tipos de bancos de dados e acessos................................................................................120

Tipos de bancos de dados...............................................................................................120Bancos de dados locais.....................................................................................................................121Servidores de bancos de dados remotos ..........................................................................................121

Arquiteturas de aplicações de bancos de dados ...............................................................121Pensando em escalabilidade.............................................................................................................122Aplicações de uma camada ..............................................................................................................123Aplicações de duas camadas ............................................................................................................123Aplicações multi-camadas ................................................................................................................124

A evolução das arquiteturas de acesso............................................................................125Terminais burros e aplicativos Desktop.............................................................................................125Aplicativos Client/Server...................................................................................................................126Aplicativos distribuídos .....................................................................................................................127

Por que escrever aplicações distribuídas?........................................................................128A tecnologia DataSnap .....................................................................................................................128Entendendo aplicações que acessam providers................................................................................129

Os protocololos da DataSnap..........................................................................................129COM, DCOM e COM+ .......................................................................................................................130CORBA .............................................................................................................................................131TCP/IP (Sockets) ..............................................................................................................................132HTTP (WEB).....................................................................................................................................133

Entendendendo datasets ................................................................................................134O que é um TDataset? .....................................................................................................................134Famílias de datasets .........................................................................................................................134Tipos de datasets .............................................................................................................................135

CAPÍTULO 10 - TRABALHANDO COM A BDE .....................................................................138

Conhecendo a BDE .........................................................................................................139Drivers usados pelo BDE...................................................................................................................139O BDE Administrator ........................................................................................................................140

Suporte Delphi a aplicações BDE.....................................................................................140Datasets baseados em BDE ..............................................................................................................140Métodos de TDatabase e TSession....................................................................................................141

Recursos avançados do BDE...........................................................................................141CACHING BLOBs...............................................................................................................................142Obtendo um handle BDE..................................................................................................................142Manipulando transações ...................................................................................................................142Usando passthroug SQL ...................................................................................................................143Usando transações locais..................................................................................................................143

Ferramentas de trabalho com a BDE ...............................................................................143

O futuro da BDE.............................................................................................................145

Page 8: Curso

DELPHI6 e tecnologias de bancos de dados

8

Acesso a dados para tabelas locais...................................................................................................145

CAPÍTULO 13 - APLICAÇÕES BASEADAS EM ADO .............................................................147

A arquitetura ADO..........................................................................................................148Tecnologia OLEDB ............................................................................................................................149Conhecendo a interface ADO ...........................................................................................................149Conhecendo a ADOExpress ..............................................................................................................150

Conectando com fontes de dados ADO ............................................................................151TADOConnection x Connection string...............................................................................................152Logins e timeout...............................................................................................................................153

Transações em ADO .......................................................................................................153Usando métodos de transações ........................................................................................................154Usando eventos de transação...........................................................................................................154

Trabalhando com comandos...........................................................................................154Especificando o comando.................................................................................................................155Usando o método Execute................................................................................................................155Cancelando comandos......................................................................................................................155Retornando dados com comandos....................................................................................................156

ADO.NET .......................................................................................................................156A arquitetura ADO.NET ....................................................................................................................157Datasets ADO.NET............................................................................................................................157Provedores de dados .NET................................................................................................................158

CAPÍTULO 14 - APLICAÇÕES INTERBASE EXPRESS ..........................................................159

A arquitetura Interbase Express .....................................................................................160Conhecendo a IBX............................................................................................................................160Herança baseada em TDataset.........................................................................................................161Datasets unidirecionais.....................................................................................................................162Extensibilidade da arquitetura IBX ...................................................................................................162

Compatibilidade inter-plataformas .................................................................................173

Conectando com bancos de dados Interbase/Firebird......................................................174

Transações no Interbase................................................................................................174Usando o TIBTransaction .................................................................................................................175Níveis de isolamento de transações ..................................................................................................175

Trabalhando com comandos...........................................................................................176O componente TIBSQL.....................................................................................................................176Executando comandos......................................................................................................................177

Controlando um servidor Interbase.................................................................................177A InterbaseAdmin ............................................................................................................................177

CAPÍTULO 15 - APLICAÇÕES BASEADAS NA DBEXPRESS ..................................................180

A arquitetura DBExpress ................................................................................................181Como trabalha a DBExpress?............................................................................................................181Tipos de datasets unidirecionais.......................................................................................................181

Page 9: Curso

DELPHI6 e tecnologias de bancos de dados

9

Conectando com um servidor SQL...................................................................................182Configurando o objeto TSQLConnection ...........................................................................................182Identificando o driver.......................................................................................................................182Especificando parâmetros de conexão..............................................................................................183Nomeando uma descrição de conexão .............................................................................................183

Especificando quais dados exibir.....................................................................................184Representando o resultado de uma consulta....................................................................................184Representando os registros em uma tabela......................................................................................184Representando uma tabela usando TSQLTable ................................................................................185Representado os resultados de uma stored procedure.....................................................................185

Obtendo os dados ..........................................................................................................186Preparando o dataset .......................................................................................................................186Transferindo dados de múltiplos datasets ........................................................................................186

Executando comandos ...................................................................................................187Métodos de execução .......................................................................................................................187

CAPÍTULO 16 - APLICAÇÕES COM PROVEDORES E DATASETS CLIENTES ..........................188

A arquitetura dos datasets clientes .................................................................................189

Estudando TClientDataset ..............................................................................................189Editando dados.................................................................................................................................189Desfazendo alterações......................................................................................................................190Salvando as alterações .....................................................................................................................191

Indexando colunas com TClientDataset ..........................................................................191Adicionando um novo índice.............................................................................................................192Excluindo e alternando índices .........................................................................................................192

Campos calculados e agregados .....................................................................................192Campos internamente calculados .....................................................................................................193Usando campos agregados...............................................................................................................193

Copiando dados de outros datasets ................................................................................194Assinalando dados diretamente........................................................................................................194Clonando um cursor de dados..........................................................................................................195

Manipulando TClientDataset com um provedor de dados .................................................195

Especificando um provedor de dados (data provider ).......................................................196

Obtendo parâmetros da aplicação servidora....................................................................196

Pasando parâmetros para a aplicação servidora..............................................................197Enviando consultas ou parâmteros de procedimentos armazenados ................................................197Limitando registros com parâmetros ................................................................................................197

Sobrescrevendo o resultset de um provedor de dados ......................................................197Requisitando dados de uma aplicação servidora ..............................................................................198

Manipulando constrições ................................................................................................199Manipulando constrições do servidor de dados.................................................................................199Adicionando constrições personalizadas ...........................................................................................200

Page 10: Curso

DELPHI6 e tecnologias de bancos de dados

10

Atualizando registros em um servidor .............................................................................200Gravando as alterações ....................................................................................................................201

Reconciliando erros de alterações ...................................................................................201Atualizações em uma só tabela ........................................................................................................201Atualizações em dados com joins .....................................................................................................202

TClientDataset com dados baseados em arquivos............................................................202O que é o modelo porta-arquivos? (briefcase) .................................................................................203Carregando dados de um arquivo ou stream ...................................................................................203Salvando dados em um arquivo ou stream.......................................................................................203

Outros datasets clientes.................................................................................................204TBDEClientDataset............................................................................................................................204TIBClientDataset...............................................................................................................................204TSQLClientDataset............................................................................................................................205

CAPÍTULO 17 – USANDO PROVEDORES DE DADOS ..........................................................206

Determinando a fonte dos dados ....................................................................................207Usando um dataset como fonte de dados ........................................................................................207Usando um documento XML como fonte de dados...........................................................................207

Comunicando-se com um dataset cliente ........................................................................207

Como aplicar atualizações com um TDatasetProvider ......................................................208

Controlando as informações em um pacote de dados.......................................................208Especificando os campos que serão inclusos ....................................................................................208Opções que influenciam os pacotes de dados ..................................................................................209Informações personalizadas em pacotes ..........................................................................................209

Respondendo a requisições de datasets clientes ..............................................................210

Respondendo a atualizações de datasets clientes ............................................................210Resolvendo erros de atualizações no provider ..................................................................................210Respondendo a eventos gerados nos clientes...................................................................................211

CAPÍTULO 18 - TRABALHANDO COM O COMPONENTE TFIELD..........................................212

A arquitetura dos componentes fields .............................................................................213Criando um novo objeto TField.........................................................................................................214Campos calculados ...........................................................................................................................214Campos Lookup ................................................................................................................................215Campos Agregados...........................................................................................................................215

Configurando propriedades de TField ..............................................................................215Conjuntos de atributos e máscaras...................................................................................................216

Manipulando eventos .....................................................................................................217

Métodos de componentes fields ......................................................................................218

Conversões de valores de campos...................................................................................218

Acessando valores de campos.........................................................................................219Acessando valores de componentes field..........................................................................................220

Page 11: Curso

DELPHI6 e tecnologias de bancos de dados

11

Conferindo o valor corrente de um field...........................................................................................220

Constrições de componentes fields .................................................................................221Constrições de servidores SQL..........................................................................................................221Constrições personalizadas ...............................................................................................................221

Descendentes complexos de TField .................................................................................222Usando campos de objetos...............................................................................................................222Trabalhando com fields ADT ............................................................................................................222Trabalhando com TArray Field .........................................................................................................223

CAPÍTULO 19 - CRIANDO UMA APLICAÇÃO DESKTOP ......................................................225

Projeto de aplicação Desktop .........................................................................................226Bancos de dados locais.....................................................................................................................226Usando ADOExpress como mecanismo de acesso.............................................................................226Modelo de dados ..............................................................................................................................227

Iniciando o desenvolvimento do aplicativo ......................................................................227Criando um novo projeto..................................................................................................................227Módulos de dados.............................................................................................................................228

Trabalhando com um módulo de dados ...........................................................................229Conectando com o banco MS Acess .................................................................................................229Inserindo datasets para acesso aos dados........................................................................................230

CAPÍTULO 20 - CRIANDO APLICAÇÕES CLIENT/SERVER ..................................................233

Introdução ao modelo cliente/servidor ...........................................................................234Arquitetura cliente/servidor ..............................................................................................................234Primeira geração cliente/servidor .....................................................................................................235Segunda geração cliente/servidor ....................................................................................................235

SGDB - Sistemas gerenciadores de banco de dados..........................................................236Modelos de banco de dados .............................................................................................................236Sistema de gerenciamento de arquivos............................................................................................237Banco de Dados Hierárquico ............................................................................................................237Banco de dados de rede...................................................................................................................238Banco de dados relacional................................................................................................................239A linguagem SQL..............................................................................................................................240Categorias da Linguagem SQL..........................................................................................................240Consistência e integridade dos dados...............................................................................................241Integridade Referencial ....................................................................................................................241Integridade Referencial Declarativa..................................................................................................242Triggers............................................................................................................................................242Domínio dos dados ...........................................................................................................................242Regras de Negócio ...........................................................................................................................243Distribuição da consistência e integridade dos dados.......................................................................243

Trabalhando com Bancos de Dados Relacionais ...............................................................243Componentes da arquitetura cliente/servidor - dlsf ..........................................................................244

Projetando Aplicações Cliente/Servidor ..........................................................................244Estrutura de uma Aplicação .............................................................................................................245Vantagens da organização da aplicação em camadas ......................................................................246Construindo Aplicações Cliente/Servidor...........................................................................................246Utilizando Interbase Express ............................................................................................................248

Page 12: Curso

DELPHI6 e tecnologias de bancos de dados

12

Componente TIBDatabase................................................................................................................249Projeto de interface do software ......................................................................................................250Trabalhando com o TQuery..............................................................................................................250

CAPÍTULO 21 - CRIANDO APLICAÇÕES MULTI-CAMADAS ................................................253

Escrevendo aplicações distribuídas .................................................................................254

Modelos de thread e instanciação de objetos...................................................................254Módulos de dados remotos...............................................................................................................254Instanciação única............................................................................................................................254Instanciação interna.........................................................................................................................254Instanciação múltipla .......................................................................................................................254Modelo de thread simples.................................................................................................................254Modelo de thread Apartment............................................................................................................254Modelo de thread livre......................................................................................................................254Modelo de thread neutro..................................................................................................................254

Modelos de thread em CORBA.........................................................................................254Modelo de thread simples.................................................................................................................254Modelo de thread múltiplo................................................................................................................254

CAPÍTULO 22 - CRIANDO UMA APLICAÇÃO PORTA-ARQUIVOS.........................................256

Page 13: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

13

CC UU RR SS OO II

DD EE LL PP HH II 66 .. 00 EE TT EE CC NN OO LL OO GG II AA SS DD EE BB AA NN CC OO SS DD EE DD AA DD OO SS

Page 14: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

14

PARTE IDELPHI, KYLIX E O OBJECT PASCAL

Na primeira parte deste programa veremos as características fundamentais do ambiente Delphi e umadescrição detalhada dos fundamentos da linguage Object Pascal. Este programa não abrange o estudodo Borland Kylix, o novo ambiente da Borland de desenvolvimento para a plataforma Linux, mas comoele é completamente baseado no Object Pascal e totalmente compatível com o Delphi 6.0, faremosmenção constatnte a este novo ambiente em muitos capítulos.

Uma vez que o programador tenha se introduzido suficientemente na programação em Object Pascal,poderá livremente usar tanto o Delphi como o Kylix, conforme suas necessidades. Mais do que isto,poderá portar seus aplicativos - com virtualmente nehuma mudança no código-fonte - para aplataforma Linux.

O princípio básico de compreensão da programação orientada a objetos é um dos aspectos maisimportantes para o desenvovedor que se aproxima do Object Pascal (em sua versão Windows ouLinux). Afirmamos que possivelmente esta é a característicaas mais forte da programação nestesambientes.

Todo o conteúdo programático é baseado na versão 6.0 do Borland Delphi.

Page 15: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

15

CC AA PP ÍÍ TT UU LL OO 11 -- VV II SS ÃÃ OO GG EE RR AA LL

Este capítulo tem como objetivo apresentar o ambiente de desenvolvimento do Delphi. Também éabordado como o Delphi se torna compatível com o Kylix, bem como os tipos de aplicativos que vocêpode criar com o Delphi 6.0.Finalamente, você poderá entender o suporte a tecnologias disponíveis no Delphi, bem como asdiferenças existentes neste aspecto com relação ao ambiente Kylix.

Page 16: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

16

O que é o Delphi?

O Borland Delphi é um ambiente de desenvolvimento de aplicações Windows bastante complexo eabrangente. Ao mesmo tempo, possui muitas características que o tornam uma ferramenta RAD (rapidapplication development). O que tem tornado o Delphi uma ferramenta preferencial para muitos éjustamente esta combinação de poder e facilidade, bem como um elemento que lhe é único: aexistência de um puro compilador assembler muito avançado e de altíssimo desempenho. Na prática,isto significa o desenvolvimento de aplicações mais rápidas, um ambiente de desenvolvimento muitomais produtivo, possibilidade de usar-se diretamente código assembler (de compilaçãoextrememamente veloz) em seu código-fonte e muito mais. Desde o lançamento do Delphi, seucompilador tem ganhado todos os testes de avaliação, superando até mesmo os mais rápidoscompiladores C. Este fato resultou na sua adoção como medida de comparação nos testes entre outroscompiladores; algo semelhante ao que acontece hoje em dia com as cotações de moedas, sempremedidas tendo como relação o dólar norte-americano.

Mas o Delphi é bem mais que um compilador potente. Os programadores Delphi sabem que têmestado constantemente sempre na vanguarda das tecnologias Windows (e agora Linux). O Delphi, defato, tem colocado o Windows de joelhos, como demonstra os recentes acordos entre a Microsoft e aBorland, reconhecendo o Delphi como ambiente de desenvolvimento prioritário de aplicativos para osistema operacional da Microsoft. A própria Borland tem sido, em parte, responsável direta pelaintrodução de alguns das mais recentes novidades lançadas no Windows 2000 em diante, como odesenvolvimento da arquitetura dos novos serviços WEB (WebServices), a portabilidade da tecnologiaXML para estes serviços (.NET), serviços DataSnap para COM+ e MTS e outras tecnologias. Estesacordos reconhecem a Borland como parceira no desenvolvimento de tecnologias para o sistemaoperacional Windows. Quanto a tudo isto, é possível encontrar uma grande massa de informações nossites da Borland e da Microsoft, bem como em muitos sites de programação Delphi.

Aplicativos Windows e aplicativos Linux

O Delphi está ligado à plataforma Windows. Todo o seu ambiente e ferramentas, bem como a suabibliotaca de objetos (VCL) são construídos tendo como base a API do Windows. O seu compilador éincapaz de gerar aplicativos para outras plataformas. Contudo, o Delphi 6.0 possui a biblioteca deobjetos CLX, que pode ser usada para a construção de aplicativos multi-plataformas, sendo a mesmacomum ao Delphi 6.0 e ao Kylix. É possível, então, construir um aplicativo CLX no Delphi e gerar umaplicativo Windows e, depois, pegar os mesmos códigos-fontes e compilá-los no Kylix, gerando assimum aplicativo Linux. A Borland poderia, simplesmente, colocar à disposição dos desenvolvedores ocompilador Kylix para executar esta tarefa, mas – talvez por razões comerciais – criou o ambiente Kylixcompleto.Como conseqüência desta estratégia, podemos ver em páginas na Internet e mídia publicitária que oKylix tem ganhado todos os prêmios de melhor ferramenta de desenvolvimento para a plataformaLinux.

Tipos de aplicativos

O sistema operacional Windows suporta três tipos básicos de aplicações:

• Aplicações Windows GUI;• Aplicações Console;• Aplicações de Serviços.

Você pode criar qualquer um destes tipos de aplicações com o Delphi.

Page 17: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

17

As aplicações GUI (Graphic user interface) do Windows talvez sejam as mais conhecidas, porquepossuem uma aparência gráfica. O próprio Delphi se enquadra neste tipo de aplicação bem como oWindows Explorer ou o Bloco de Notas. Evidentemente, dentro deste tipo de aplicação existem muitascom funções extremamente diversificadas ou, ainda, aquelas que incorporam objetos em seu ambiente(como objetos COM ou derivados).Qunado você escolhe a criação de um novo aplicativo VCL (File|New Application) está criando umdestes aplictivos.

As aplicações console são executáveis 32bits que são ativados através de comandos, como na linhade comando ou na tela Executar do Windows. Aplicações console são extremamente numerosas noambiente Windows, e você executa diversas vezes algumas delas ao longo de um tempo trabalhandoem seu computador. Para criar um aplicativo console, escolha File | New e, na janela que se abre.Seleciona o ícone “Console Wizard”.

Aplicações de serviços são, talvez, as mais “misteriosas” para o susuário comum. Consistem,basicamente, em servidores que executam requisições de programas clientes e retornam a elesinformações. Estas aplicações rodam tipicamente em background, sem muita ação do usuário. Umservidor WEB, FTP ou POP são alguns dos exemplos de aplicações de serviços. Para criar uma destasaplicações, escolha File | New | Items. Na janela que se abre, escolha o ícone “Service Application”.

Apesar das características bastante diversificadas de cada um destes tipos de aplicações, você asdesenvolve sempre da mesma maneira no ambiente Delphi, em um ambiente gráfico, usandoabordagens próprias de linguagens orientadas a objetos e com grande reaproveitamento de código.

Suporte a tecnologias

O Delphi oferece um muito amplo suporte a tecnologias e padrões do ambiente Windows. Na prática,não há nada que funcione neste sistema operacional que você não possa fazer em Delphi. Você podedesenvolver executáveis de todos os tipos, dll’s, objetos COM, ActiveX, Type Labriries, AutomationServers, Automation Controlers, Servidores ASP, COM+ ou MTS, serviços WEB de todos os tipos, telasde descanso, fontes True Type (TTF) e ainda outros. Além de tudo isto, você pode desenvolver tambémobjetos, controles ou formulários WEB usando ActiveX.Para efeito de melhor compreensão, podemos destacar este suporte da seguinte maneira:

• Tecnologias de aplicativos: envolvem a criação de qualquer tipo de aplicativo e arquivo quevocê desejar. Aqui podemos ver executáveis diversos, multimídias, bibliotecas dinâmicas (dll’s) econtroladores de serviços.

• Tecnologias COM: envolvem um infinidade de objetos, interfaces etc que se encontram emexecutáveis. Servidores e controladores Automation, Servidores COM em ou fora de processo,ActiveX, Servidores ASP, COM+ e objetos derivados do COM que suportam o ambiente MTS.

• Tecnologias voltadas para Internet: envolvem a criação de servidores ou clientes WEB, Pop,WebServices, CGI’s, ISAPI, NSAPI, páginas ASP, WinCGI, Browsers etc.

• Tecnologias de Banco de Dados: é uma das áreas onde o Delphi oferece o maior suporte. Vocêpode criar aplicativos de banco de dados que usam literalmente qualquer fonte de dados. Existesuporte diferenciado e baseado em mais de uma tecnologia para acesso a bancos Xbase, Acess,Paradox, FoxPro, VisualFoxPro, Sybase, Interbase, FireBird, Oracle, MS SQLServer, Informix, DB2,Arquivos Texto, Fontes ODBC, XML/CDS (MyBase), Formatos personalizados. Você também podeescolher o uso de tecnologias de acesso diferentes, tais como: Fontes OleDB, ADO, DAO, Acessonativo via API de SGDB’s, BDE, DBExpress. Se você mesmo desenvolver uma arquitetura de banco

Page 18: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

18

(com formatos personalizados), o Delphi lhe permite desenvolver drivers IBExpress, BDE, OLEDB ouobjetos com base em TDataset que atendam a este novo formato proprietário.

Versões do Delphi

O Delphi 6 é distribuído em três versões diferentes. Estas versões diferem significativamente quantoaos recursos e ferramentas disponíveis:

• Enterprise. É aversão completa do produto. Esta versão suporta todas as tecnologias descritasacima.

• Professional. É uma versão voltada para desenvolvedores que não trabalham com aplicaçõesdistribuídas e WEBServices. Alguns recursos (como a DataSnap e WEBSnap) não estão disponíveis,mas podem ser adquiridos separadamente. Você pode desenvolver aplicativos de banco de dadoscom esta versão.

• Standard. É a versão mais simples. Originalmente, ela foi disponibilizada para estudantes, masvocê perceberá que ainda assim é uma ferramenta poderosa. Veja, por exemplo, um sumário dosrecursos disponíveis nesta versão: compilador Object Pascal otimizado, bibliotecas VCL e CLX,suporte a pacotes, uma IDE com muitos recursos, suporte completo à API do Windows.

Delphi.NET

Mais recentemente a Borland anunciou o lançamento de uma versão do Delphi totalmente adapdata àsnecessidades do framework .NET, também recentemente adotado pela Microsoft. Não podemos discutiraqui o que seja a tecnologia .NET, e afirmaremos apenas que tem o objetivo de prover odesenvolvimento de porte de aplicativos para a internet. A maneira como isto pode ser feito é autilização de serviços WEB (conhecidos, então, como WEBServices) e aplicativos distribuídos, usandotecnologias mais recentemente introduzidas no desenvolvimento para internet, como SOAP, ADO.NET eXML. Com o Delphi 6, você já é plenamente capaz de criar aplicações .NET. Existem muitos exemplosde aplicativos deste tipo já disponíveis. Dem observado, a própria Borland é uma das parceiras daMicrosoft para o desenvolvimento da arquitetura .NET, conforme ditam alguns acordos assinados noano passado; a Borland tem sido, de fato, provedora de tecnologias para esta arquitetura. Isso explicao fato de, em um determinado momento, o Delphi (e outras ferramentas da Borland) já possuiremsuporte à tecnologia .NET, antes mesmo de a Microsoft implementar tais tecnologias em suasferramentas.

O lançamento do Delphi 7.0 (codinome “Aurora”) está anunciado para ocorrer na segunda metade doano de 2002, o do Kylix 3 (codinome “Cortez”) para julho de 2002, e o lançamento da versão 8.0 doDelphi (com codinome “Galileo”) já está prevista para 2003. Como se isto não fosse suficiente, aBorland também já anunciou o lançamento, também para o segundo semestre de 2002, de uma versãodo Delphi estritamente direcionada para o desenvolvimento WEB e dedicada ao framework .NET. Estaferramenta já possui o nome comercial oficial de Delphi.NET.

Page 19: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

19

Hoje, acredita-se que a migração dos aplicativos Windows para a arquitetura .NET é uma certeza.Muitos especialistas espimam que, dentre 3 anos, todos os novos desenvolvimentos de aplicaçõesWindows estarão baseados na arquitetura .NET. Você já pode começar a criar aplicativos quetrabalham nesta arquitetura, desde já.

O que é o Kylix?

Historicamente, o desenvolvimento de aplicações para Linux usando as ferramentas tradicionais temsido uma experiência de custosas tentativas. Ferramentas Linux tradicionais, como GCC e Emacs sãodifíceis de aprender e não provêem a produtividade que os desenvolvedores corporativos demandam.O Kylix altera esta situação.

O Kylix introduz, no sistema operacional Linux, uma solução de desenvolvimento de alto desempenhoque integra, a partir da versão 3.0, o desenvolvimento de aplicativos usando as linguagens ObjectPascal do Delphi e, por outro lado, C++. A criação de aplicativos de banco de dados, GUI, WEB eWEBServices é agora uma experiência muito mais rápida e simples com o Kylix. Como o Linux continuaa crecer como uma solução viável para aplicações corporativas, de e-business, de bancos de dados,GUI, WEB e WebServices, você pode se beneficiar de todos os recursos implementados no ambienteKylix para oferecer-lhe um ambiente de desenvolvimento de aplicações muito rápido. De fato, osespecialistas afirmam que o Kylix é o primeiro ambiente RAD (rapid application development)disponível para o mundo Linux. E devemos ainda acrescentar: ao contrário de muitas outrasferramentas, o Kylix já nasceu grande e completo, pois surgiu como uma “transposição” do já muitodesenvolvido ambiente Delphi 5.0 para a plataforma Linux.

Escolhendo uma linguagem de desenvolvimento

Figura. Uma visão cortada do Delphi.NET com o projeto ConvertIt.dpr aberto

Page 20: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

20

O kylix surgiu originalmente como um ambiente de desenvolvimento que usa a linguagem ObjectPascal. Como grande parte dos programadores para Linux tradicionalmente desenvolvem na linguagemC, a Borland introduziu o suporte ao desenvolvimento usando a linguagem C++ no Kylix 3.0, a fim desuavizar ainda mais o esforço de aprendizado destes programadores.

O Kylix 3 provê ambas linguagens de programação ANSI/ISSO C++ e Object Pascal, duas poderosaslinguagens orientadas a objetos em uma única ferramenta de desenvolvimento. Outra vantagemoferecida pelo Kylix é a integração de ambientes. O ambiente de desenvolvimento do Kylix (toda a IDE)é praticamente idêntico ao fornecido pelo Delphi, de forma que um programador Delphi se sentirá “emcasa” ao abrir o Kylix pela primeira vez. Isto permitirá um ganho de produtividade enorme para osprogramadores Kylix/Delphi.

Tipos de aplicativos

Com o Kylix você pode desenvolver qualquer tipo de aplicativo para Linux. Você pode desenvolveraplicativos visuais, serviços, bibliotecas compartilhadas, aplicativos WEB etc. Podemos enumerá-los daforma que segue:

• Aplicativos visuais: são programas que possuem uma interface (GUI) com o usuário.• Bibliotecas: são programas compilados que exportam seus recursos para outros programas. São

semelhantes às dll’s da plataforma Windows.• Aplicações de banco de dados: são aplicações que acessam e manipulam dados de um banco de

dados.• Aplicações WEB. São aplicativos que fornecem algum tipo de funcionalidade em uma página da

Internet, e servem como servidores WEB.• WEBServices. São aplicativos distribuídos que atuam como programas com funcionalidades

específicas, e são acessados através de uma página da Intenet.

Suporte a tecnologias

De modo geral, o Kylix suporta todas as tecnologias presentes no ambiente Delphi, exceto aquelas quese referem a recursos inexistentes no Linux. A ausência mais marcante é o suporte à tecnologia COM,que é exclusiva do mundo Windows. Contudo, existem algumas outras diferenças, como ausência desuporte à Registry e a alguns bancos de dados inexistentes na plataforma Linux. Um resumo do amplosuporte oferecido pelo kylix para o mundo Linux é fornecido abaixo:

• Tecnologias de aplicativos: envolvem a criação de qualquer tipo de aplicativo e arquivo quevocê desejar. Aqui podemos ver executáveis diversos, multimídias, bibliotecas compartilhadas econtroladores de serviços.

• Tecnologias voltadas para Internet: envolvem a criação de servidores ou clientes WEB, Pop,WebServices, CGI’s, ISAPI, NSAPI, WinCGI, Browsers etc.

• Tecnologias de Banco de Dados: o suporte está baseado na arquitetura flexível de TDataset eno uso da DBExpress como mecanismo de acesso a dados. Você pode acessar bancos de dadosOracle, Firebird, Interbase, Informix, DB2, MySQL e outro. Adicionalmente, o acesso a bancosInterbase ou Firebird pode ser feito de forma direta, através da Interbase Express.

Page 21: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

21

• Tecnologias de acesso distribuído: o Kylix oferece grande suporte ao desenvolvimento detecnologias de aplicações distribuídas, tanto no desenvolvimento de servidores como no de clientes.

Versões do Kylix

O Kylix 3 também é distribuído em três versões diferentes. Analogamente ao Delphi, as versões diferemmuito quanto aos recursos e ferramentas disponíveis. Veja abaixo a relação das versões:

• Enterprise. É aversão completa do produto. Esta versão suporta todas as tecnologias descritasacima. A IDE vem com mais de 200 componentes instalados

• Professional. É uma versão voltada para desenvolvedores que não trabalham com aplicaçõesdistribuídas e WEBServices. Alguns recursos (como a DataSnap, BizSnap e WEBSnap) não estãodisponíveis, mas podem ser adquiridos separadamente. Você pode desenvolver aplicativos debanco de dados com esta versão. A IDE vem com mais de 165 componentes instalados

• Open. É uma versão freeware e simples. Não é uma versão de código-fonte aberto, como o nomepode sugerir. Consiste, basicamente, de um compilador Linux e uma IDE com bem menos recursosdo que a das outras versões. A CLX vem com pouco mais de 75 componentes.

Page 22: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

22

CC AA PP ÍÍ TT UU LL OO 22 -- OO AA MM BB II EE NN TT EE DD EE LL PP HH II

O Object Pascal é uma linguagem compilada de alto nível e fortemente tipada que suporta designestruturado e orientado a objetos. Seus benefícios incluem um código de fácil leitura. Rápidacompilação e o uso de múltiplas unidades de arquivos que propicia uma programação modular. ObjectPascal oferece também recursos especiais que suportam um framework de componentes e umaambiente RAD. Você poderá usar o Object Pascal para desenvolver qualquer tipo de aplicação usandoferramentas de desenvolvimento da Borland, tais como Delphi ou Kylix.

Page 23: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

23

O ambiente Delphi

O ambiente de desenvolvimento do Delphi é muito complexo. Você encontrá uma infinidade derecursos para o desenvolvimento dos mais diversos tipos de aplicações. Uma característica marcantedeste ambiente é a quantidade de ferramentas simultaneamente dispostas para uso do desenvolvedor.Algumas delas, contudo, são de uso evidente em praticamente todos os projetos que você desenvolver,como o Code Editor, o Object Inspector e o Object Treeview. Na maioria das vezes, você perceberá queo seu ambiente será marcado pela presença de janelas (ou formulários) que você criou e nos quaistanto trabalha de forma visual (desenhando a janela) como escrevendo código no Code Editor.Abaixo você pode ver uma imagem do ambiente Delphi com algumas de suas mais importantesferramentas:

A Janela Principal

A janela principal do Delphi é um mecanismo de acesso fácil aos recursos do ambiente. Tambémdenominada IDE, é na verdade um recurso extremamente dinâmico, podendo Ter seus menu’s, botõesetc completamente alterados tanto pela configuração do usuário quanto pela instalação decomponentes e addin’s. A instalação destes últimos podem criar menus extras, novas ferramentas naIDE etc. Todas estes recursos instaláveis na IDE (existem centenas ou milhares deles na internet) sãocriados no próprio Delphi.Observer abaixo o exemplo da ComponentBar, que agiliza o acesso aos objetos instalados na IDE.A janela principal também abriga a palheta de componentes, onde residem os componentes disponíveispara uso. Você deve analizar detalhadamente esta janela, pois descobrirá uma quantidade muitograndes de recursos novos e ferramentas que facilitam muito o trabalho de desenvolvimento.

Page 24: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

24

O Editor de Código (Code Editor )

O Editor de código providencia total acesso ao código gerado pelo projeto, incluindo alguns dos maispoderosos recursos para a edição. Pode ser selecionado tipos de cores para os elementos do programa(como por exemplo comentários, palavras reservadas, códigos assembler, ...). O Editor de Código seráusado por você sempre que desejar escrever algum código em seu aplicativo. Também possui muitosrecursos relacionados à navegação entre código e unidades, debugação de aplicativos e muitos outrosrecursos. Para outras informações adicionais sobre o modo de usar este editor, procure referências noHelp OnLine no tópico Code Editor .Ao ser aberto um novo projeto, o Delphi gera automaticamente na página do Code Editor uma Unitcom o arquivo código (.PAS). Para ver o código de uma Unit em particular, simplesmente Click natabulação de página. O Code Editor mostrará sempre o nome do arquivo corrente ativo na tabulaçãode página.Você pode personalizar por completo o comportamento e a aparência do Code Editor.

O Object Inspector

Providencia a conexão entre a interface visual e o código de seu aplicativo. É composto por duaspáginas Properties (propriedades) e Events (Eventos) que mostram respectivamente as propriedades eeventos do objeto selecionado. O Object Inspector também disponibiliza um fácil caminho para apersonalização dos objetos. Você usará a página de Propriedades para personalizar os objetoscolocados no formulário (inclusive o próprio formulário), e a página de Eventos para gerenciar anavegação entre certas partes do código do programa ou escrever novos manipuladores de eventos.O seletor de objetos (Object Selector - localizado em um objeto do tipo ComboBox no topo do ObjectInspector) mostra o nome e o tipo de todos os componentes do formulário corrente (inclusive opróprio). Você pode usar o seletor de objetos para localizar facilmente qualquer objeto no formulário.Ferramentas do tipo do Object Insector são comuns em muitos ambientes de desenvolvimento visual esão de muito fácil compreensão. O Object Inspector pode ser completamente personalizado pelousuário. A personalização envolve desde a sua aparência até o ocultamento/exibição de algumaspropriedades dos objetos. O uso desta ferramenta é uma constante na maioria dos projetos, podendoser acessada, por padrão, através da tecla F11.

O ObjectInspectorexibindo apágina depropriedades deum objeto.

O ObjectInspectorexibindo apágina deeventos de umobjeto.

Page 25: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

25

O Object Treeview

Esta ferramenta permite uma visualização hierárquico dos objetos em um formulário a partir dapespectiva da vinculação entre eles. Ou seja, existe um formulário e dentro deles diversoscomponentes; dentro de cada um destes componentes podem haver outros a eles vinculados e assimpor diante. Não confunda isto com a representação hierárquica de descendência dos objetos instaladosna IDE. O Object Treeview pode ser usado para selecionar qualquer objeto que, por qualquer razão,estiver escondido ou oculto atrás de outros objetos. Esta seleção equivale à seleção direta que você fazcom o cursor mouse.

Figura X:O Object TreeViewexibindo os objetos emum container (Form1).

Page 26: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

26

A Palheta de Componentes

Componentes são alguns dos objetos que você usará para trabalhar em suas aplicações. Oscomponentes são acessados através de várias páginas da Palheta de Componentes. Lá você poderáencontrar caixas de diálogos, controles de edição, datasets, botões e muito mais. Por padrão, osobjetos da palheta são alocados em diferentes páginas, segundo as suas próprias funcionalidades. Porexemplo, os objetos que representam as janelas tradicionais do Windows (tais como fontes, palheta decores, ...) foram colocados na página Dialogs da palheta.

Você poderá criar seus próprios objetos, assim como também instalar outros já prontos. Uma dasprincipais vantagens da OOP é que existe no mercado, lieralmente falando, uma infinidade de pacotesde objetos prontos para serem integrados aos sistemas, o que facilita ainda mais o desenvolvimento e amanutenção dos mesmos.

Você pode personalizar por completo a palheta de componentes, mudando a organização doscomponentes e os nomes das páginas. Para isto, basta acessar a janela “Pallete Properties” usando omenu de contexto em cima da Palheta de Componentes e selecionando o item “Properties”. Nestajanela, é possível criar novas páginas, deletar as existentes e mover componentes de uma página paraoutra.

Ao trabalhar no desenho de telas em um aplicativo a Palheta de Componentes é vastamente usada.Uma característica implantada a partir do Delphi 6.0 é ocultamento dos ícones dos controles quando

Figura – Um visão cortada da Palhetade Componentes.

FiguraA janela “Pallete Properties”permite quevocê opere uma todal personalização daPalheta de Componentes. Através dosbotões, você cria uma nova página naPalheta ou renomeis, move ou eliminauma existente. Você pode mover oscomponentes de uma página a outrasimplesmente arrastando-os para apágina listada à esquerda.

Page 27: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

27

você está trabalhando em um módulo de dados (ou um de seus descendentes). Isto é lógico, pois éimpossível colocar um controle em módulos de dados.

O Object Repository

O Repositório de Objetos (Object Repository) do Delphi armazena e gerencia os objetos da aplicação:Formulários, Data Modules, geradores experts, e DLL (Dinamic Linked Library - Bibliotecas de acessodinâmico). Na essência, ele centraliza as localizações dos objetos envolvidos agrupado-os. Aproliferação dos objetos no repositório incrementa as seguintes vantagens:

• Suporte a equipe de desenvolvimento para referência aos objetos da rede.• Uma customização de todo o desenvolvimento em grupos lógicos de objetos, facilitando o re-uso

dos mesmos.

O Delphi possui diversas características quanto a sua utilização. Tem os Tutors e Experts que são asferramentas responsáveis para guiar-nos através de técnicas, tais como, manipulação de componentese criação de simples aplicações. Além disso o Delphi oferece uma coleção de modelos para formulários,janelas de diálogo e até mesmo aplicações completas na ferramenta New Items. A janela do NewItems é sempre chamada automaticamente quando a opção File | New | Items do menu principal éexecutada.É possível para você criar novas janelas, ou projetos, automáticos no Delphi. Para definir o projetopadrão que o New Items executará no início de cada projeto, clique com o botão direito acima dajanela e escolha a opção Properties aparecerá as listas Pages e Objects, defina quaisquer dos objetoscomo New Form ou Main Form.

Observe que a segunda folha da janela New Items (terá o nome do seu arquivo com a extensão .DPR)é o seu projeto corrente, ou seja, uma nova janela poderá ser derivada, por característica de herança,de uma outra janela já existente. Muitos assistentes são inicializados a partir desta ferramentas

FiguraxUma visão doObjectRepository.Como estaferramenta écustomizál, vocêpode encontraruma visão muitodiferente destaferramenta emuma instalação doDelphi.

Page 28: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

28

O Project Manager

O Gerenciador de Projetos contém uma lista de formulários ou unidades utilizados pela aplicação, eserve para controlar estes formulários ou unidades, adicionando-os ou removendo-os do projeto,organizando as opções do projeto, entre outros. Isto significa que você pode gerenciar de formacentralizada diversas aplicações em um só local. Projetos maiores, envolvendo alguns aplicativos sãoexcelentemente gerenciados através desta ferramenta. Você poderá “pular” de um projeto para outrosem fechar qualquer um deles e, quando quiser, retornar ao projeto inicialmente aberto.O Project Manager é a maneira usada pela IDE do Delphi de você trabalhar com mais de um projetoao mesmo tempo. Veja abaixo um exemplo do uso do Projetc Manager em um projeto múltiplo.

FiguraX – O Project Manager permite uma manipulação rápida e simples de projetosque contenham diversos aplicativos, bibliotecas etc.

Page 29: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

29

Organização do programa

No Object Pascal os aplicativos são comumente divididos em módulos de código-fonte chamadosunidades (units). Cada programa começa com um cabeçalho que especifica o nome do programa. Estecabeçalho é seguido por uma opcional cláusula uses e o bloco de declarações e procedimentos. Nacláusula uses encontra-se uma lista de unidades que estão ligadas ao programa, que podem serdistrtibuídas ou usadas por deferentes programas. Isto instruirá o compilador com informaçõies sobredependências entre os diversos módulos. As unidades podem estar ligadas a formulários (TForm) ouconter procedimentos e funções ou códigos de objetos ou todas estas coisas.Devido ao fato de as informações estarem armazenadas diretamente nas unidades, programasdesenvolvidos em Object Pascal não necessitam de “makefiles”, arquivos de cabeçalho ou diretivas“include” de pré-processador.

Arquivos fontes pascal

O compilador espera encontrar código Pascal em arquivos de três tipos:

•Arquivos-fontes de unidades (terminam com a extensão .pas)• Arquivos de projetos (terminam com a extensão .dpr)• Arquivos-fontes de Pacotes (terminam com a extensão .dpk)

Muito comumente, arquivos de unidades contêm a maior parte do código de uma aplicação. Cadaaplicação possui um único arquivo de projeto (.dpr) e muios arquivos de unidades (.pas). O Delphiautomaticamente mantém um arquivo de projeto para cada aplicação. Se você estiver compilando umprograma a partir de linhas de comando, é possível colocar todo o código em arquivos de unidades.Contudo, se estiver usando a IDE do Delphi para fazê-lo, deverá incluir um arquivo de projeto.Arquivos de pacotes são similares aos de projeto, mas são usados para construir bibliotecas dinâmicas(dll’s) especiais cahamadas packages (pacotes).

Outros arquivos de aplicações

Em adição aos módulos de código-fonte, são usados muitos aarquivos que não possuem código Pascalno desenvolvimento de sua aplicação. Estes arquivos são mantidos automaticamente e incluem:

• Arquivos de formulários, que possuem a extensão .dfm (Delphi) or .xfm(Kylix).• Arquivos de recursos, que possuem a extensão . res• Arquivos de opções de projeto, com extensão .dof (Delphi) ou .kof (Kylix).

Um arquivo de formulário é simultâneamente um arquivo texto e um arquivo compilado que possuibitmaps, strings e outros recursos. Cada arquivo representa um único formulário em sua aplicação. AIDE do Delphi permite você salvar estes arquivos como texto ou binário. Freqüentemente, cadaaplicação possui ao menos um formulário (principal), e cada formulário possui um arquivo .pasassociado a ele que, por padrão, tem o mesmo nome do formulário associado a ele.

Cada projeto usa també um arquivo de recurso (.res) que armazena bitmaps, ícones, cursores equalquer outro tipo de dado binário.Os arquivos de opções de projetos contêm diretivas de compilação, informações de diretórios depesquisa, informações de versões etc. Por padrão, estes arquivos têm o mesmo nome do aruivo deprojeto (.dpr).

Page 30: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

30

Várias ferramentas na IDE do Delphi armazenam dados em arquivos de outros tipos, como arquivos dedesktop (.dsk), que contêm informações sobre as posições das janelas e outras opçÕes deconfiguração. Estes arquivos não possuem qualquer efeito direto na compilação.

Arquivos gerados pelo compilador

A primeira vez que você compilar uma aplicação ou dll, o compilador produz um arquivo de unidadecompilada .dcu (Windows) .dcu/.dpu (Linux) para o seu projeto. Assim, quando você recompilar a suaaplicação ou biblioteca, as unidades .pas não serão novamente compiladas, exceto se você as alterouou see o compilador não pode encontrá-las. É possível também instruir o compilador paraforçosamente gerar novamente os arquivos compilados.

Uma simples aplicação console

O exemplo seguinte ilustra alguns recursos básicos da programação em Object Pascal. Trata-se de umasimples aplicação console que não pode ser compilada a partir da IDE, mas sim a partir da linha decomando.

program Greeting;{$APPTYPE CONSOLE}var MyMessage:string ;beginMyMessage :='Hello world!';Writeln(MyMessage);end .

A primeira linha declara um programa chamado Greeting. A diretiva {$APPTYPE CONSOLE} informa ocompilador que se trata se uma aplicação console. A próxima linha declara uma variável do tipo string,chamada MyMessage. O programa então atribui a esta variável a string “Hello world!” e envia oconteúdo da variável para o output padrão usando a procedure Writeln, que é definida na unidadeSystem, que é incluída automaticamente pelo compilador em toda aplicação.

Você pode escrever este programa em uma arquivo chamado Greeting.pas e compilá-lo digitando

On Delphi:DCC32 GreetingOn Kylix:dcc Greeting

na linha de comando.

Apesar de o Delphi/Kylix serem ambientes de desenvolvimento muito voltados para a criação deaplicativos com aspectos gráficos (e com certeza muito mais complexos), você pode criar livrementeaplicações de linha de comando que não possuem qualquer interface com o usuário. Estas ferramentasoferecem completo suporte ao desenvolvimento de aplicações do tipo console.

Alguns recursos importantes da IDE

Page 31: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

31

A IDE do Delphi e do Kylix oferece muitos recursos interessantes. A finalidade deles é facilitar oprocesso do desenvolvimento dos seus aplicativos. Neste tópico vamos destacar alguns deles. Lembre-se que, tão logo você os conheça e utilize, jamais deixará de utilizá-los em todas as suas aplicações.

Encaixe de janelas (Dock)

O Delphi e o Kylix usam o modelo de interface SDI (single document interface), o que siginifica quemuitas janelas podem ser abertas separamente uma das outras e ao mesmo tempo. Se você é umdesenvolvedor que utiliza ferramentas como C++ ou Visual Basic, já deve Ter reparado que estemodelo é constantemente usado rm quase todas as ferramentas de desenvolvimento de aplicativos.

Contudo, pode ocorrer que, após abrir umas 30 janelas, a sua área de trabalho fique confusa. Parasolucionar este problema, o Delphi e o Kylix oferecem o recurso de encaixe de janelas. Este recursoresume-se ao encaixe de muitas janelas em uma única janela, tal como se fossem painéis. Quandovocê arrasta uma janela em cima de outra o Delphi a encaixará automaticamente, mas se você nãodesejar que o encaixe seja feito, arraste-a novamente para fora da região de encaixe. Se você estáarrastando uma janela (como quando vai organizar a posição das janelas), mas não deseja que a IDEencaixe-a, aperte a tecla Ctrl enquanto executa o arrasto.

Você pode identificar que existem janelas encaixadas através da barra horizontal que as separa. Paradesfazer o encaixe, basta arrastar uma janela para fora da superfície da outra onde está encaixada. Aimagem abaixo mostra algumas janelas da IDE do Delphi encaixadas:

Preenchimento de classes

O preenchimento de classes é um recurso que tem o objetivo de poupar digitação do programador.Freqüentemente nós sabemos exatamente qual código escrever, mas somos obrigados a digitar umagrande quantidade de código. O preenchimento de classes tenta resolver este problema através daseguinte estratégia:

FiguraXO Object Inspector encaixadona janela do ObjectTreeView.

Este é o ObjectInspector

Este é o ObjectTreeView

Page 32: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

32

Você digita uma declaração (como em um procedimento e função) e aperta as teclas Ctrl+Shift+C afim de que a IDE possa escrever uma estrutura de código que você teria de escrever manualmente,caso não existivesse o prrenchimento de classes.

Por exemplo, você cria um procedimento chamado “Teste”, que requer uma parâmetro inteirochamado simplesmente “I”. Algo como:

procedure Teste(I: integer)

Ao apertar a combinação de teclas que citamos acima, a IDE escreverá a implementação desteprocedimento para você, que é algo como:

procedure Teste(I: integer);begin

end;

Lembre-se deste recurso ao declarar novos procedimentos e funções, pois ele poupará muito do seutempo de trabalho, além de minimizar as possibilidade de erros.

Navegação entre seções de interface e implemntation

Outro recurso interessante da IDE se refere à navegação entre as declarações e implementações dosprocedimentos e funções em uma unidade. Se você está na implementação de um procedimento,aperte as teclas Ctrl+Shift+ seta para cima para ir para o local do código onde a declaração doprocedimento foi feita. O caminho inverso é feito através das teclas Ctrl+Shift+ seta para baixo. Vocêficará feliz ao usar este recurso em unidades código muito extensas.

AppBrowser

Ao escrever uma aplicação, muitas vezes você se deparará com uma linha de código que se refere aum método não escrito por você. Se desejar ver o código deste método, aperte a tecla Ctrl enquantopassa o cursor do mouse em cima do nome do método, e clique neste nome. Imediatamente a IDElocalizará a unidade onde o método é implementado, e a abrirá na linha onde o método éimplementado.

Você pode usar este recurso da mesma forma que faz com um navegador de internet, clicando em“links” para se mover a um determinado lugar. Há também uma lista dos lugares visitados, de formaque você pode retornar ou avançar na navegação por esta lista.

Page 33: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

33

TO-DO ListO recurso TO-DO List da IDE é uma ferramenta de gerenciamento de tarefas a serem realizadasdurante o desenvolvimento de um aplicativo. Consiste basicamente em um cadastro de tarefas queainda precisam ser feitas por um determinado usuário. TO DO List é completamente integrado na IDE,de forma que você poderá incluir uma nova tarefa a partir de qualquer unidade de código de suaaplicação. Por exemplo, em qualquer ponto do ser código, acesse o menu de contexto e selecione oitem “Add To-Do Item”. Isto fará com que a janela de gerenciamento de tarefas apareça, a fim de quevocê insira uma nova tarefa a ser feita naquele ponto do código. Você pode, igualmente, criar novastarefas que não estão vinculadas a nenhum código específico, como “Inserir logotipo da empresa noprograma”, e muitos outros recursos. A imagem abaixo mostra o gerenciados de tarefas da IDE comalgumas tarefas concluídas e outras não.

Code Insight

O code insight é simplesmente um recurso que poupa-lhe o trabalho excessivo de digitação durante odesenvolvimento de seus programas. Basta você digitar o nome de um identificador, seguido de umponto, para o code insight exibir em uma lista fllutuante todas as propriedades, eventos, métodos etccabíveis ao identificador. Agora, basta selecionar o que você deseja para a IDE escrever o códigocorrespondente para você e, em seguida, fechar a janela com a lista. Se, por alguma razão, a janela sefor fechada antes de você escolher um item, aperte as teclas Ctrl+ barra de espaço para exibí-lanovamente.

Page 34: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

34

CC AA PP ÍÍ TT UU LL OO 33 –– CC OO NN HH EE CC EE NN DD OO OO OO BB JJ EE CC TT PP AA SS CC AA LL

Este capítulo introduzirá um primeiro conhecimento do que é a linguagem Object Pascal. Vocêperceberá que o Object Pascal é uma linguagem completamente orientada a objetos e,conseqüentemente, qualquer desenvolvimento que puder ser feito nesta linguagem deve sempre Terem mente este fato.Embora muitos conceitos errôneos possam surgir a respeito do que seja uma linguagem orientada aobjetos, podemos afirmar que todo o suporte que uma linguagem orientada a objetos pode ofereceraos desenvolvedores, em última instância, encerra-se no processo de criação de novas classes eobjetos. Poderia-se dizer: a linguagem se desenvolve à medida que o conjunto de objetos disponívelcresce. Apesar da simplificação natural a este raciocínio, você compreenderá que é válido para aslinguagens orientadas a objetos.

Você também conhecerá a estrutura fundamental de uma unidade de código do Object Pascal.Qualquer programa é construído a partir destas unidades de código-fonte, que chamamos units, quesão ligadas e compiladas são para gerar uma aplicação. As unidades permitem:

• Dividir grandes programas em módulos que podem ser editados separadamente.• Criar bibliotecas que você pode compartilhar entre diversos programas.• Distribuir bibliotecas para outros desenvolvedores sem tornar o código-fonte disponível.

Page 35: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

35

Programação orientada a objetos

Para compreendermos melhor o ambiente de desenvolvimento Delphi é necessário que você aprenda etenha em mente os conceitos de OOP (Programação Orientada a Objetos). Não confunda os conceitosintroduzidos à programação orientada a objetos com a EOP (Programação Orientada a Eventos), muitodifundida a partir do Access 2.0 © (um ambiente baseado em Objetos). Ao longo deste tópico você vainotar as sensíveis diferenças que existem entre esses dois conceitos.A OOP e a EOP são às vezes confundidas, mas lembre-se: a OOP contém a EOP, mas a EOP nãocontém a OOP. Ou seja, um objeto pode existir, mesmo que não exista nenhum evento associado a ele,mas um evento não pode existir se não houver um objeto a ele associado.

Outros conceitos que podem causar confusão são o de Ambientes Orientados a Objetos e o deAmbientes Baseados em Objetos. Em ambientes orientados a objetos, consegue-se criar e manipularobjetos, mas, naqueles ambientes que são apenas baseado em objetos, não é possivel a criação deobjetos, apenas a sua manipulação. O Microsoft Visual Basic (VB) é um dos exemplos mais típicos deambientes baseados em objetos. Quando a Microsoft lança uma nova versão do VB, os programadorespodem verificar que novos objetos foram adicionados, mas nenhum daqueles pode fazê-lo por contaprópria no VB; esta adição é feita, em muitos casos, criando-se bibliotecas dinâmicas em outrasferramentas. Outro exemplo de fácil compreensão: muitas ferramentas de desenvolvimentoimplementam alguns aspectos de orientação a objetos, como propriedades e eventos, mas isto nãosignifica que são orientadas a objetos. O fato de possuirem elementos de programação denominadosobjetos e algo como propriedades e eventos de objetos, por si só, não compõem sequer o centrodaquilo que é chamado programação orientada a objetos. Na verdade, uma linguagem não orientada aobjetos não poderá jamais chegar a possui esta característica, a não ser que sofram umatransformação tão profunda que poderíamos, neste caso, dizer que uma nova linguagem foi criada. Oque é possível fazer, então, é torná-la cada vez mais baseada em objetos.

Originalmente, a OOP é um conceito desenvolvido para promover uma programação estruturada efacilitar a reutilização de códificações. Por exemplo, quando você adiciona um componente na suaaplicação, o que está fazendo é reaproveitamento de codificação. Sendo a Borland, uma das primeirasempresas a promover o estudo e a aplicação deste novo conceito, é natural que tenha desenvolvido asprincipais linguagens de programação (tais como Object Pascal e C++), totalmente orientadas aobjetos. Com o tempo, a OOP atraiu muitos adeptos, atraídos principalmente pela grande reutilizaçãode código e as facilidades de crescimento de uma estrutura de dados (como uma hierarquia deobjetos, por exemplo) que ela proporcionava. Entre estes programadores, por exemplo, pode-se citaraqueles que desenvolviam em Clipper’87 ©, ferramenta muito utilizada no final da década de 90 einício da década de 90.

Este tópico introduzirá alguns conceitos fundamentais da programação orientada a objetos, que é abase fundamental do desenvolvimento na linguagem Object Pascal.

Orientação a objeto

Como se vê programação orientada a objetos é uma extensão da programação estruturada queenfatiza a reutilização de código e o encapsulamento de dados com funcionalidade. Desde que vocêtenha criado um objeto (ou, mais formalmente, um classe), você e outros programadores podem usá-loem diferentes aplicações, reduzindo o tempo de desenvolvimento e aumentando a produtividadeAntes de começarmos a falar realmente de linguagem orientada a objetos e necessário que vocêpossua os conceitos básicos da orientação a objetos, são eles:

Objeto - é qualquer estrutura modular que faz parte de um produto. Uma janela por exemplo, é umobjeto de uma casa, de um carro ou de um software com interface gráfica para o usuário.

Page 36: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

36

Atributos - São as características do objeto, como cor e tamanho, a janela, por exemplo, tem atributoscomo o modelo, tamanho, abertura simples ou dupla, entre outros.

Encapsulamento - é um mecanismo interno do objeto “escondido” do usuário. Uma pessoa pode abriruma janela girando a tranca sem precisar saber o que há dentro dela.

Ação - é a operação efetuada pelo objeto. Todas as janelas, por exemplo, controlam a iluminação etemperatura ambiente, dependendo do seu design.

Herança - um objeto novo nem sempre é criado do zero. Ele pode “herdar” atributos e ações deoutros já existentes. Um basculante herda atributos das janelas e das persianas.

Polimorfismo - é a capacidade de objetos diferentes reagirem segundo a sua função a uma ordempadrão. O comando “abre”, por exemplo, faz um objeto entrar em ação, seja ele uma janela, umaporta ou uma tampa de garrafa.

Ligação - é quando um objeto conecta a sua ação a outro. Um sensor de claridade, por exemplo, ativao acendimento automático da iluminação de rua.

Embutimento - Permite a um objeto incorporar funções de outros, como um liqüidificador que móicarne com a mudança do tipo da lâmina.

O Object Pascal

O Object Pascal é uma linguagem completamente orientada a objetos. Na prática, isto significa que odesenvolvimento em Object Pascal é feito sempre com peças de construção de aplicativos, que sãochamados genericamente de objetos. Para os programadores que já conhecem técnicas de estruturasde programação, com o C, Basic, Pascal ou xBASE, entre outras linguagens, o Object Pascalprovidencia uma migração de forma natural, mas oferecendo um produto de maior complexibilidade.Uma das conseqüências da orientação a objetos do Object Pascal, é que você é forçado a executarpassos lógicos durante o desenvolvimento, tornando mais fácil o desenvolvimento de aplicativos detodos os tipos. Além disso possibilita a criação e reutilização (vantagem de reuso tão sonhado com aOrientação a Objetos) de objetos e bibliotecas dinâmicas (Dynamic Link Libraries - DLL).

O Object Pascal contém todo o conceito da orientação a objetos, incluindo aspectos mais sensíveis,como encapsulamento, herança e polimorfismo. Algumas extensões foram incluídas para facilitar o usotais como conceitos de propriedades particulares e públicas, e tipos de informações em modo runtime,manipulação de exceções, e referências de classes. O resultado de toda esta junção faz com queObject Pascal consiga suportar as facilidades de um baixo nível de programação, tais como:

• Controle e acesso das subclasses do Windows© (API);• Passar por cima das mensagens de loop do Windows©;• Mensagens semelhantes às do Windows©;• Uso direto da linguagem Assembler.

Ao mesmo tempo, o Object Pascal se revela como uma linguagem de alto nível, isto é, que encapsulaas funcionalidades e recursos de programação em uma solução de fácil implementação. Isto torna oObject Pascal uma linguagem extensa, com a qual se pode desenvolver tudo. Para não parecer umexagero, durante os próximos capítulos você poderá observar que, literalmente falando, não existenada, no mundo Windows, que você não possa fazer usando o Objetc Pascal.

Page 37: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

37

Evidentemente, uma linguagem orientada a objetos não precisa, necessariamente, ser uma linguagemcom recursos visuais. Isso fica fácil de se entender quando observamos que um objeto é uma estruturade dados, que pode ou não possuir características relacionadas à visibilidade e aparência (como cor,altura, largura etc). Bem observado, a maioria dos objetos implementados no Object Pascal nãopossuem caracacterística alguma relacionada à visibilidade.

O que é um objeto?

Um objeto ou classe é um tipo de dado que encapsula dados e operações sobre dados em uma únicaunidade. Antes da programação da programação orientada a objetos dados e operações (funções)eram tratados como elementos separados. Você pode começar a entender objetos se entender records.Records são estruturas de campos que contêm dados onde cada campo tem o seu próprio tipo. Objetossão também coleções de elementos de dados, mas – diferentemente de records – contêmprocedimentos e funções que operam nos seus dados. Tais procedimentos e funções são chamadosmétodos. Um objeto também é acessado atraves das suas propriedades. A combinação da dados efuncionalidade em uma única unidade é chamada emcapsulamento. Adicionalmente, a programaçãoorientada a objetos é caracterizada por herança e polimorfismo. A herança indica que os objetosderivam suas funcionalidades de outros objetos (chamados ancestrais), mas o objeto atual podemodificar suas características herdadas. O polimorfismo significa que diferentes objetos herdados domesmo ancestral suportam as mesmas propriedades e métodos que, podem ser chamadosintercambiáveis.

Quando você declara uma classe, é possível especificar seu ancestral imediato. Por exemplo:

Type TSomeControl = class (TControl);

Isto é a classe declarada TsomeControl descende de Tcontrol, desta forma herdando todas ascaracterísticas de Tcontrol e seus ancestrais.

A classe TObject, declarada na unidade system, é o ancestral último de todas as outras classes. Nestaclasse podemos encontrar todos os métodos básicos de criação e destruição de objetos, que serãousados ou modificados pelos descendentes de TObject.

Classes, objetos e componentes

Este tópico apresenta uma visão geral das bibliotecas de componentes e introduz alguns doscomponentes que você pode usar no desenvolvimento de suas aplicações. Delphi inclui ambas a VisualComponent Library (VCL) e a Borland Component Library for Cross-Platform (CLX). A VCL é apenaspara desenvolvimento de aplicações Windows, enquanto a CLX é usada para desenvolvimento deaplicações Windows ou Linux. São duas diferentes bibliotecas, porém possuem grandes similaridades.A VCL e a CLX são bibliotecas de classe e objetos, alguns dos quais são também componentes oucontroles que você usa no desenvolvimento de suas aplicações. Alguns objetos na VCL implementamrecursos que estão disponíveis apenas na plataforma Windows. Tais objetos aparecem nas palhetasADO, BDE, QREPORT, COM +, WebServices e Servers. Virtualmente todos os objetos da CLX estãodisponíveis para as plataformas Linux e Windows.

Um subconjunto de objetos são os componentes. Você pode coloca-los em um formulário ou módulo dedados e manipulá-los em tempo de desenvolvimento; também é possível especificar suas propriedadessem escrever código. Todos os componentes da VCL ou CLX descendem do objeto Tcomponent.

Page 38: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

38

Os componentes são objetos no verdadeiro sentido da programação orientada a objetos (OOP) porquê:

• Encapsulam um conjunto de dados e funções de acesso a dados;• Herdam dados e características dos objetos dos quais são derivados;• Operam intercambiavelmente com outros objetos derivados de um ancestral comum, característica

chamada polimorfismo.

Diferentemente de muitos componentes, objetos não aparecem na palheta de componentes. Umavariável padrão é declarada na unidade do objeto ou você tem que declará-la. Controles são tiposespeciais de componentes que são visíveis para o usuário em tempo de execução. Todos os controlestem propriedades que especificam seus atributos visuais, tais como altura, largura ou cor. Aspropriedades, métodos e eventos que todos os controles tem em comum são herdados de Tcontrol.

Programação estruturada e syntax

Um programa contém:

• Um cabeçalho• Uma cláusula uses (opcional)• Um bloco de declarações e procedimentos

O cabeçalho do programa especifica um nome para o programa. A cláusula uses lista as unidadesusadas pelo programa. O bloco contém as declarações e procedimentos que são executados quando oprograma roda. A IDE espera encontrar estes três elementos em um único arquivo .dpr.

O exemplo abaixo mostra o código de um programa chamado Editor

1 program Editor;23 uses4 Forms,{change to QForms in Linux}5 REAbout in 'REAbout.pas'{AboutBox},6 REMain in 'REMain.pas'{MainForm};78 {$R *.res}910 begin11 Application.Title :='Text Editor';12 Application.CreateForm(TMainForm,MainForm);13 Application.Run;14 end .

A linha 1 contém o cabeçalho. A cláusula uses vai da linha 3 à 6. A linha 8 é uma diretiva decompilação que liga o programa a um arquivo de recurso. Das linhas 10 à 14 vemos o bloco deprocedimentos. Esta é uma típica unidade de projeto, geralmente bem pequenas e totalmentemantidas pela IDE.

Unidades estruturadas e syntax

Page 39: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

39

A unidade consiste de tipos (incluindo classes), constantes, variáveis, e rotinas (funções eprocedimentos). Cada unidade é definida no seu próprio arquivo .pas. Após o cabeçalho e a cláusulauses seguem-se as seções interface, initialization e finalization. As seções initialization e finalization sãoopcionais. O esqueleto de uma unidade parece-se com o que segue:

unit Unit1;

interfaceuses {List of units goes here }{Interface section goes here }

implementationuses {List of units goes here }{Implementation section goes here }

initialization{Initialization section goes here }

finalization{Finalization section goes here }end .

Nota: A unidade deve conter a palavra end seguida de um ponto. Os nomes de unidades devem serúnicos dentro de um mesmo projeto.

A seção Interface

A seção interface se inicia com a palavra interface e continua até o início da implementação da seçãoimplementation. Ela declara constantes, tipos, variáveis, procedimentos e funcões que estão disponíveispara clientes, isto é, para outras unidades ou programas que usam a unidade na qual é declarada.Estas entidades são chamadas públicas porque um clienmte pode acessá-las como se fossemdeclaradas no próprio cliente.A declaração de interface de um procedimento ou função inclui apenas o cabeçalho das rotinas.Também todos os membros de todas as classes usadas na unidades são declaradas aí, comotipicamente ocorre em uma unidade vinculada a um formulário.

A seção Implementation

A seção implementation começa com a palavra-reservada implementation e continua até o início daseção initialization ou, caso esta última não exista, até o fim da unidade. A seção implementationdefine procedimentos e funções declaradas na seção interface, que podem ser colocadas em qualquerordem. Nesta seção você pode também declarar constantes, tipos (inclusive classes), variáveis etc quesão privadas a esta unidade, isto é, inacessíveis a clientes, além de sua própria cláusula uses. Nesteúltimo caso, a cláusula deve aparecer imediatamente após a palavra-reservada implementation.

A seção Initialization

Page 40: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

40

Como dissemos, a seção initialization é opcional. Começa com a palavra-reservada initialization etermina até o início da seção finalization ou, se esta não existir, até o final da unidade. A seçãoinitialization contem rotinas que são executadas, na ordem em que aparecem, na inicialização doaplicativo. Por exemplo, se você definiu estruturas de dados que precisam ser inicializadas, você podefazer isto nesta seção. A seção initialization de unidades usadas por um cliente são executadas naordem que as unidades aparecem na cláusula uses.

A seção Finalization

A seção finalization também é opcional e pode aparecer apenas em unidades que têm uma seçãoinitialization. Ela começa com a palavra-reservada finalization e termina no final da unidade. Aí sãocolocadas rotinas que são executas quando o aplicativo é encerrado. A liberação de memória erecursos que devem estar disponíveis ao longo de toda uma execução de um aplicativo pode ser feitanesta seção.Seções finalization são executas em ordem oposta às initialization. Por exemplo: se seu aplicativoinicializou as unidades A, B e C – nesta ordem -, elas serão finalizadas na ordem C, B e A. Desde queuma seção initialization de uma unidade de código inicia sua execução, automaticamente garante-se aexecução da respectiva seção finalization quando o aplicativo for encerrado.

Nota: O código de uma seção finalization deve ser escrito de forma a suportar possíveis falhas queocorram na seção initialization como, por exemplo, na execução incompleta de uma rotina alocadora dememória.

Referências circulares

Entende-se pela expressão “referência circular” o fato de uma determinada unidade de código (.pas)fazer referência a outra unidade em sua cláusula uses que, por sua vez, também se refira a estaunidade. O exempla abaixo ilustra esta situação.

unit unit1;

interfaceUses windows, sysutils, unit2;.....

e, por sua vez a segunda unidade:

unit unit2;

interface

uses windows, sysutils, unit1; //A unidade unit1 já faz referência a esta!...

Este tipo de prática não desencadeia um erro de compilação, mas freqüentemente indica um erro nodesenvolvimento lógico (engenharia) do aplicativo. Por que a primeira unidade faria referência à

Page 41: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

41

Segunda e esta, por sua vez, à primeira? Com certeza, são bem poucas as situações onde esta prática énecessária.

Identificadores, diretivas, palavras-chaves

Identificadores denotam constantes, variáveis, campos, tipos, propriedades, funções, programas,unidades, bibliotecas e pacotes. Um identificador pode ser de qualquer comprimento, mas apenas osprimeiros 255 caracteres são significativos. Um identificador deve começar com uma letra ou traça-baico (underscore) e não podem conter espaços; letras, dígitos e traços-baixos são permitidos após oprimeiro caracter. Palavras reservadas não podem ser usadas como identificadores. Uma vez que oObject Pascal é uma linguagem insensitiva, um identificador como CalculateValue poderia ser escritode qualquer uma destas maneiras:

CalculateValuecalculateValuecalculatevalueCALCULATEVALUE

Nota: No Kylix, os únicos identificadores que são case-sensitive são os nomes de unidades. Desde que onome de algum identificador corresponda ao do nome do arquivo pascal, inconsistências podem, àsvezes, afetar a compilação.

As seguintes palavras reservadas não podem ser usadas como identificadores:

and initialization try library dispinterfacedown packed case record gototo thread file until notin var is constructor setor asm property for whilestring except type mod divarray In class repeat ifelse line finalization uses objectinherited procedure label destructor shlout begin raise function withthen exports unit nil doas interface const resourcestring implementationshr xor of var finallyend program

Adicionalmente, as palavras private, protected, public, published e automated agem comopalavras reservadas dentro de declarações de tipos de objetos, mas, do contrário, não são tratadascomo diretivas. As palavras on e at também têm significado especial.

Diretivas

Diretivas são palavras que são senditivas a locais específicos dentro do código-fonte. Elas ocorremapenas em locais onde identificadores definidos pelo usuário não podem existir. Conseqüentemesnte –

Page 42: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

42

apesar de não recomendável – você pode definir identifadores com usando palavras que são diretivasem outros locais. Abaixo são fornecidas as lista de palavras que agem como diretivas.

absolute safecall default implements pascaldynamic assembler published override reintroducemessage external stored readonly writeonlyprivate near cdecl virtual dispidresident public forward package localabstract stdcall overload register platformexport automated read write requiresname far varargs deprecated indexprotected nodefault contains library

Page 43: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

43

CC AA PP ÍÍ TT UU LL OO 44 -- TT II PP OO SS DD EE DD AA DD OO SS EE EE SS TT RR UU TT UU RR AA SS

Um tipo (type) é essencialmente um nome para um tipo de dado. Quando você declara uma varávelvoce deve especificar seu tipo, que determina o conjunto de valores que a variável pode armazenar.Muitas funções e procedimentos requerem parâmetros de diversos tipos.O Object Pascal é uma linguagem fortemente “tipada”, o que quer dizer que ela distingüe umavariedade de tipos de dados e nem sempre permite a substituição de umtipo por outro. Normalmenteisto é benéfico porque permite ao compilador tratar os dados inteligentemente e validar seu código demaneira mais rígida, previnindo error de tempo de execução que são dificilmente diagnosticados.Quando você precisa de maior flexibilidade, existem mecanismos para sobrescrever a forte tipagem.Tais mecanismos incluem conversão de tipos (typecastting), ponteiros (pointers), variants, variantsparts em records e endereçamento absoluto de variáveis (absolute addressing). Contudo, entenda quea forte tipagem é um recurso altamente benéfico, e só em casos muito específicos você abrandariaesta característica do compilador.

Page 44: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

44

Classificação

Simplificadamente, os tipos podem ser classificados como simples, estruturado, ponteiro, procedural ouvariant.

Simples

Tipos “simples”, que inclue, tipos ordinais e reais, definem um ordenado conjunto de valores.Os tipod “ordinais” incluem integer, character, boolean, enumerated e subrange. A tabela abaixo defineos tipos inteiros mais importantes com suas respectivas faixas de valores:

Tipo Faixa FormatoInteger –2147483648..2147483647 signed 32-bitCardinal 0..4294967295 unsigned 32-bitShortint –128..127 signed 8-bitSmallint –32768..32767 signed 16-bitLongint –2147483648..2147483647 signed 32-bitByte 0..255 unsigned 8-bitWord 0..65535 unsigned 16-bitLongword 0..4294967295 unsigned 32-bitInt64 –2 63 ..2 63 –1 signed 64-bit

Tipos subrange

Tipos subrange representam um subconjunto de valores em um outro tipo ordinal (chamado tipobase). Por exemplo, se você declara o tipo enumerado:

type TColors =(Red,Blue,Green,Yellow,Orange,Purple,White,Black);

Você pode então definir um tipo subrange como:

type TMyColors =Green..White;

Aqui, TmyColors inclui os valoress Green, Yellow, Orange, Purple, e White.

Tipos real

Um tipo real define um conjunto de números que podem ser fracionários. A tabela abaixo descreve ostipos real mais importantes.

Tipo Faixa FormatoReal48 2.9 x 10–39 .. 1.7 x 1038 6Single 1.5 x 10–45 .. 3.4 x 1038 4Double 5.0 x 10–324 .. 1.7 x 10308 8Extended 3.6 x 10–4951 .. 1.1 x 104932 10Comp –263 +1 .. 263 –1 8Currency –922337203685477.5808.. 922337203685477.5807 8

Page 45: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

45

Nota: O tipo real genérico é idêntico ao tipo double.

Tipos string

Uma string representa uma seqüência de caracteres. A tabela abaixo fornece as informações maisimportantes quanto a estes tipos.

Tipo ComprimentoShortString 255 caracteresAnsiString ~231 caracteresWideString ~230 caracteres

O tipo padrão é a AnsiString. O tipo WideString é usado para servidores de tecnologia COM edesenvolvimento de bibliotecas de tipos (type library), uma vez que é compatível o tipo BSTR da COMdo Win32.Há ainda o tipo Pchar, que é uma string terminada em nulo (#0). Este tipo é muito usado emchamadas de funções da API do Win32, uma vez que strings terminadas em nulo são usadas de formapadrão nesta plataforma. O operador + pode ser usado para concatenar strings e você pode usar umavariável do tipo string como uma lista de caracteres. Por exemplo:

...

procedure CancatenaTexto;vars: string;begins := ‘Delphi. ’;s := s + ‘Olá pessoal’; // ‘Delphi. Olá pessoal’

end;

Tipo Boolean

Os tipos Boolean são muito simples e conhecidos de muitos programadores de outras linguagens.Referem-se a dados que são verdadeiros (true) ou falsos (false). Estes tipos são usados massivamenteao longo de um aplicativo.

Tipos estruturados

Os tipos estruturados incluem conjuntos (sets), arrays, records e files. As instâncias de tipoestruturado armazenam mais do que um valor. Por padrão, os valores de um tipo estruturado estãoalinhados em uma face ou dupla face para um acesso mais rápido e, quando você define um destestipos poderá usar a palavra reservada packed para emplementar armazenagem comprimida de dados.O uso de compressão reduz o desempenho de acesso aos dados, no caso de um array de caracteresafeta a compatibilidade de tipos. Um exemplo de um tipo enumerado “empacotado” é o que segue:

Type Tnumbers = packed array[1..100] of Real;

Page 46: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

46

Conjuntos (sets)

Um conjunto é uma coleção de valores de um mesmo tipo ordinal. A faixa de um tipo set é um tipoordinal específico chamado de base type; isto é, os valores possíveis de um tipo set são todos o subsets de um base type, inclusive um conjunto vazio. O base type não pode Ter mais do que 256 valorespossíveis, e suas ordinariedade deve estar entre 0 e 255. Devido à limitação de tamanho, tipos set sãousualmente definidos com subfaixas (subrange), como no exemplo abaixo:

Type TsomeInts = 1.. 250; TintSet = set of TsomeInts;

Arrays

Um array representa uma coleção indexada de elemetos de um mesmo tipo (também chamada baseType). Como cada elemento tem um índice único, os arrays, diferentemente dos tipos set, podemconter um mesmo valor mais de uma vez. Os arrays podem ser alocados de forma estática oudinâmica.

Arrays estáticos são definidos na sua forma de construção

Array [indtype1, ..., indtypeN] of baseType

Onde cada indtype é um tipo ordinal cuja faixa não excede 2 GB. Uma vez que indType indexa o array,o número de elementos em em array pode ser limitado pelo produto dos tamanhos de indType. Naprática, indType são usualmente subconjuntos inteiros. Em um caso mais simples de um arrayunidimencional a apenas um único índice. Por exemplo,

var MyArray: array[1..100] of Char;

declara uma variável chamada MyArray que armazena um array com valores de 100 caracteres. Dadaesta declaração, MyArray[3] indica o terceiro caracter neste array. Se você cria um array estáticomas não assinala valores para todos os seus elementos, os elementos não preenchidos ainda assim sãoalocados e contêm valores randômicos. Um array multidimencional é um array de arrays, como noexemplo:

Type Tmatrix = array[1..10] of array[1..50] of Real;

Que é equivalente a:

Type Tmatrix = Array[1..10, 1..50] of Real;O array Tmatrix representa um array de 500 valores do tipo Real.

Page 47: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

47

Arrays dinâmicos

Arrays dinamicos não têm um tamanho ou comprimento fixos. Ao contrário, a memoria para eles érealocada quando você assinala um valor para o array ou o passa para o procedimento SetLength. Tipode arrays dinâmicos são indicados pelas seguintes construções:

Array of buseType

Por exemplo,

var MyFlexibleArray: array of Real;

Declara um array dinâmico unidimencional de valores do tipo Real. A delcaração não aloca memóriapara este array; para fazê-lo chame o procedimento setLength como abaixo,

SetLength(MyFlexibleArray, 20);

Aloca um array de 20 elementos do tipo Real, indexados de 0 a 19.

Records

Um registro (record) representa um conjunto de elementos heterogéneos, onde cada elemento échamado um campo (field). A declaração de um tipo record especifica o nome e tipo para cada campo,como abaixo,

Type recordTypeName = record FieldList1: type1; . . . fieldListn: typen;end

Por exemplo a seguinte declaração cria um tipo record chamado TdateRec.

Type TDateRec = record Year: Integer; Month: (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); Day: 1..31;End;

Cada TdateRec contem 3 campos: um valor inteiro chamado Year, um valor de tipo enumeradochamado Month, e outro campo inteiro com valores entre 1 e 31 chamado day. Os identificadores Year,Month, Day, são os designadores de campos para TdateRec, e eles se parecem muito com variáveis.Contudo, a declaração do tipo TdateRec não aloca memoria para seus campos, o que somente ocorreráquando você inicializar o Record, como abaixo:

var Record1, Record2: TdateRec;

Você pode ler os campos de um Record acessando-os através de seus nomes:

Record1.Year := 1904;Record1.Month := Jun;

Page 48: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

48

Record1.Day := 16;

Agora é possível também copiar os valores dos campos de Record1 para Record2:

Record2 := Record1;

Tipos Record são comumente usados para guardar-se dados em arquivos com formato proprietário;isto é, você define os campos de um Record, grava-os conforme descrito acima e, finalmente, podecriar um tipo file que se referencie a este tipo de Record. Seguindo o exemplo acima, temos:

Calendario = file of Record1;

Isto indica o uso de um tipo file que guarda dados obtidos a partir de um Record. Existem diversosmétodos na VCL e CLX para salvar estes dados em disco.

Tipos variant

Algumas vezes é necessário manipular dados cujos tipos variam ou não podem ser determinados emtempo de compilação. Nestes casos, uma opção é usar variáveis e parametros do tipo variant, querepresenta valores que podem mudar de tipo em tempo de execução. Os tipos variant oferecem maiorflexibilidade mas consomem mais memória do que os tipos regulares, e operações sobre eles são maislentas do que sobre os tipos regulares. Além disto operações ilícitas sobre tipos variant durante aexecução de um aplicativo frequentemente resultam em erros, quando situações similares poderiamser identificadas em tempo de compilação quando usamos tipos regulares.

Por padrão, tipos variants podem armazenar valores de qualquer tipo, exceto record, set, arrayestático, file, class, referências de classes e ponteiros. Você pode definir um tipo variant customizado afim de extender as capacidades do tipo original. Tipos variant são definidos cirando-se desendentes daclasse TcustomVariantType.

Tipo OleVariant

OleVariant é um tipo de dado muito semelhante ao tipo Variant, mas só pode conter dados compatíeiscom OLE Automation. Isto significa que você pode passar dados entre programas ou em uma rede semse preocupar se os aplicativos saberão manipuá-los. Quando você assinala um tipo Variant que contemdados personalizados (tal como uma string pascal) para um OleVariant, ocorrerá uma conversãoautomática para um dos tipos padões reconhecidamente aceitos para um tipo OleVariant. Por exemplo,um tipo variant contendo um AnsiString, qunado assinalado para um OleVariant, vem a ser convertidoem um tipo WideSting. O exemplo abaixo ilustra o uso de tipos variant e OleVariant que sofremconversões implícitas:

function RetornaVariant: OleVariant;varV: variant;beginV := 0;V := ‘Delphi’;V := 32.45;

Page 49: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

49

Result := V;

end;

Como se vê acima, a variável V recebe valores de tipos diversos e retorna (em uma OleVariant) oresultado da função.

O estudo detalhado dos tipos variant, Olevariant e semelhantes é fundamental para a compreensão detecnololgias derivadas da COM, como DCOM, COM+, ASP, MTS e ainda outras.

Conversões de tipos

Em diversos momentos do desenvolvimento de um aplicativo, você terá a necessidade de converter umtipo de dado para outro. O Object Pascal oferece muitas rotinas de coversão de fácil uso eautomaticamente protegidas contra falhas. Isso quer dizer que seu aplicativo não gerará um exceçãodurante a execução que forçará seu encerramento ou o travamento de algum recurso do Kernel dosistema operacional.A tabela abaixo descreve as principais funções de conversão disponibilizadas com o Object Pascal:

Função/Método DescriçãoStrToInt Se possível, converte um string para um inteiro.IntToStr Converte um inteiro para um string.FloatToStr Converte um tipo Float para um string.FloatToStrF Converte um float para um string usando um formato específico, precisão e dígitos.StrToFloat Se possível, converte um string para um Float.PChar Converte um string pascal para um string char.StrToCurr Se possível, converte um string para um tipo Currency.CurrToSTr Converte um Currency para um string.DateToStr Converte um TDate para um string.DateTimeToSTr Converte um TDateTime para um string.TimeToStr Converte um TTime para um string.StrToDateTime Se possível, converte um string para um TDateTime.StrToDate Se possível, converte um string para um TDate.StrToTime Se possível, converte um string para um TTime.VarToStr Converte um variant para um string.StrToVar Converte um string para um variant.StrToInt64 Se possível, converte um string para um inteiro longo.StingToGUID Se possível, converte um string para um TGUID.BinToHex Se possível, converte um binário para um hexadecimal.BoolToStr Converte um boolean para um string.StrToBool Se possível, converte um string para um boolean.CompToCurrency Converte um Comp para um currency.CompToDouble Converte um comp para um double.HexToBin Se possível, converte um hexadecimal para um binário.StrToInt64Def Se possível, converte um string que representa um inteiro (decimal ou hexadecimal) para um

número.StrToIntDef Se possível, converte um string que representa um inteiro (decimal ou hexadecimal) para um

número.Converts a string that represents an integer (decimal or hex notation) to a number.

Inc Incrementa um número em um determinado valor.Dec Decrementa um número em um determinado valor.

O Delphi instala um aplicativo de demonstração, denominado “ConvertIt” que é um conversor dediversos tipos de unidades. Ele pode converter, por exemplo, quilômetros para metros, séculos para

Page 50: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

50

semanas ou segundos, nanogramas para quilos etc, etc. Você pode estudar este aplicativo paraentender como muitas conversões são feitas.

Veja a seguir alguns fragmentos de código que ilustram o uso de algumas destas funções deconversão:

varS: string;beginS := DateTimeToSTr(NOW);ShowMessage(‘Este momento é: ‘ + S);

end;

Conversões implícitas e explícitas

Conversões explícitas são aquelas executadas explicitamente através de uma das diversas rotinas deconversão disponíveis no Object Pascal. Por exemplo, quando você chama a função de conversãoIntToStr em qualquer ponto de seu código, isto significa que você está executando uma conversãoexplícita. Contudo, o Object Pascal aceita alguns tipos de conversões implícitas, isto é, aquelas que nãosão feitas através de funções de conversão, mas sim através de um operador. Veja um exemplo.

function Soma: integer;beginResult := 3 + ‘1’;end;

O compilador entende 3 como um número, mas ‘1’ é simplesmente uma string. Como o operador desoma “+” indica uma operação matemática de soma, o compilador irá tentar converter ‘1’ para umnúmero, a fim de conseguir somá-lo com o valor 3. Se o compilador conseguir fazer isto, umaconversão implícita terá ocorrido.

Nota: você não deveria usar conversões implícitas, exceto em situações muito peculiares. O ObjectPascal oferece um enorme conjunto de métodos de conversão de tipos de dados, e você sempreencontrará um que atenada às suas necessidades.

Trabalhando com strings

Strings são tipos de dados muito simples e comuns. Em Objetc Pascal, você sempre usa algum tipo destring em seus programas. Na verdade, nós a usamos massivamente. Com o passar dos anos, o ObjectPascal foi disponibilizando diversos tipos de strings para atender necessidades específicas, como, porexemplo, o acesso aos tipos char de muitas funções da API do Windows ou o uso de WideString para odesenvolvimento de aplicativos que implementam qualquer tecnologia COM ou dela derivada.

Page 51: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

51

Neste tópico, estudaremos alguns tipos de strings disponibilizadas pelo Object Pascal, bem comomuitos métodos de trabalho com elas.

Concatenando strings

Chamamos concatenação de strings o ato de unirem-se duas ou mais strings em uma só. No ObjectPascal, você concatena strings seguindo a mesma estratégia usada na soma de números. Por exemplo,se você escreve algo como

Soma := 3 + 1;

entende-se que a variável “Soma” assumiu o valor da adição matemática destes dois números.

Mas, em um outro contexto, o compilador também entenderá código

Frase := ‘Oi pessoal! ‘ + ‘O Delphi é uma boa ferramenta!’;//Agora, a variável “frase” é: ‘Oi pessoal! O Delphi é uma boaferramenta!’

ou ainda

Frase := ‘Bom dia pessoal! ’ + ‘Agora são ‘ + TimeToSTr(Time) + ‘ horas!’;//A variável “Frase” é o resultado da concatenação de três strings.

Como você pode observer, o compilador simplesmente “monta” uma nova string “ajuntando” duas oumais strings. O interessante de tudo é que você usa o mesmo operador “+” para somas matemáticas econcatenações de strings.

Um recurso de concatenação menos conhecido é a função Concat. Esta função concatena um númeroarbitrário de strings. Ela possui um parâmetro, que é um array de strings a serem concatenadas. Ovalor de retorno de Concat é uma string com as substrings concatenadas. Veja o exemplo abaixo:

var

S: string;begin S := Concat('Oi ', ' amigos!'); { 'Oi amigos!' }end;

Uma vez concatenadas, não é possível desfazer a operação automaticamente.

Nota: a função Concat é mais lenta do que o uso do operador “+”.

Page 52: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

52

Manipulando strings

Existem muitas funções destinada à leitura e manipulação de uma string. Na verdade, você podeexistem funções para você fazer o que quiser com uma string. A tabela abaixo sumariza algumasdestas funções:

Procedimento/Função

Descrição

Length Retorna o comprimento de uma determinada string (número de caracteres).Pos Retorna o índice do primeiro caracter em uma substring especificada que existe em uma dada string.Delete Deleta uma substring de uma determinada string.Insert Insere uma substring em uma determinada posição de uma string.UpperCase Altera todos os caracteres de uma string para caracteres maiúsculos.LowerCase Altera todos os caracteres de uma string para caracteres minúsculos.Val Converte uma string para uma representação numérica.Trim Elimina todos os espaços em branco de uma string.TrimLeft Elimina todos os espaços em branco de uma string.TrimRight Elimina todos os espaços em branco de uma string.StuffString Insere uma substring em uma posição especificada de uma string, substituindo os caracteres existentes.Str Formata qualquer número para uma string usando uma variável.CompareStr Compara duas strings para verificar se são idênticas.DupeString Retorna a auto-concatenação de uma string um determinado número de vezes.QuotedStr Retorna um string com o sinail ‘ inseridos em seu início e fim.ReverseString Retorna uma string invertida.SetString Determina o conteúdo e comprimento de uma dada string.WrapeText Retorna uma determinada string “quebrada” em múltiplas linhas.

Vamos ver agora alguns exemplos do uso destas rotinas.

Copiando strings

A função Copy retorna uma string que é uma cópia de um trecho de outra string. Este trecho échamado “substring”, e é definido por dois parâmetros da função Copy:

• Index. É a posição do caracter de onde a cópia deve iniciar;• Count. É o número de caracteres a serem copiados.

Por exemplo, considere a string ‘Delphi is rad!’. Uma cópia que partisse do primeiro caracter e copiasse6 caracteres resultaria a string ‘Delphi’. Como em

varS: string;beginS := Copy(‘Delphi is rad!’,0,6); // s é agora ‘Delphi’end;

Ou, em um outro exemplo

S := Copy(‘Delphi is rad!’,8,7); / s é agora ‘is rad!’

Como você percebeu, o primeiro caracter de uma string possui sempre o índice 0.

Page 53: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

53

Inserindo strings

O procedimento Insert adiciona uma substring em uma string. Seu funcionamento difere das rotinasde concatenação de strings, pois, ao contrário destas, Insert é capaz de inserir a substring emqualquer ponto da string original. Por exemplo, você pode inserir uma substring qualquer após oquarto caracter da strings original. Insert exige 3 parâmetros:

• Source. É a substring que se deseja inserir;

• S. É a string na qual uma substring será inserida

• Index. É a posição na qual se insere S.

Veja um exemplo

Insert(‘Delphi is a tool!’, ‘rad ’, 10); //’Delphi is a rad tool!’

Existem apenas algumas observações a serem feitas:

Se Index for menor do que 1, será convertido para 1. Se Source for uma string vazia, nada será feito.

Caso não seja possível alocar memória suficiente para armazenar a nova string, uma exceção do tipoEoutOfMemory será disparada.

Deletando strings

O método Delete pode deletar uma substring determinada de uma outra string. Delete requer 3parâmetros.

S. É a string da qual será deletada uma substring (um trecho de string).

Index. Marca a posição a partir da qual serão deletados os caracteres.

Count. Determina a posição final de demarcação da string a ser deletada.

Considere o seguinte exemplo

Delete(‘Delphi is a rad tool!’, 13, 4); //’Delphi is a tool!’

Se Index é for maior do que o comprimento de S ou menor do que 1, nada será feito. Se Countespecifica mais caracteres do que os restantes na string S, todo o resto da string é deletado. Se Counté menor do que 0, nenhum caracter é deletado.

Formatando strings

Page 54: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

54

O Object Pascal fornece muitas rotinas destinadas à formatações de strings. Formatar uma string é aação de, a partir de uma string com indicadores de formatação, retornar uma string com os valoresreais em substituição aos indicadores. Por exemplo, considere a função Format. Esta função retornauma string não formatada a partir de parâmentros de formatação fornecidos por você. Veja umexemplo.

varS: string;

beginS := Format(‘Delphi is a rad %s!’,[‘tool’]); //’Delphi is a rad tool!’ShowMessage(S);end;

Format requer um conjunto de parâmetros composto da string formatada e dos valores a serem usadosna formatação. Mas a função Format é muito mais valiosa do que é possível perceber através doexemplo acima. Format é capaz de lidar com diversos tipos de dados, não apenas strings. No exemploacima %s é um indicador de formatação de strings (s), mas você poderia escrever algo assim.

varS: string;

beginS := Format(‘Delphi %d is a %s!’,[6,‘tool’]); //’Delphi 6 is a rad tool!’ShowMessage(S);end;

Neste caso o indicador %d (decimal) é substituída por um número decimal. Format pode formatarargumentos de muitos tipos, e possui uma estrutura flexível. Você pode formatar dados inteiros,decimais, monetários, hexadecimais etc. Para uma referência completa, consulte a ajuda on-line doDelphi.

Mais sobre strings...

Um fanático por estudar e brincar com strings poderia escrever livros sobre este assunto. Atualmente,são tantos os tipos de strings suportados pelo Object Pascal, que existe uma tonelada de informaçõessobre estes tipos. Existem informações incríveis sobre strings na ajuda do Delphi. Consulte a seção“strings handling routines”, por exemplo, para ver uma lista completa das funções e procedimentos demanipulação de strings.

Lembre-se sempre: strings são tipos de dados que você sempre usará. Desenvolvendo um grande sitede internet ou um joguinho muito pequeno, você sempre precisará das strings.

Trabalhando com datas

A coisa mais importante que você deve ter em mente quando escrever aplicativos que trabalhamintensamente com datas é o fato de as datas serem expressas de forma muitos diferentes ao longo dasdiversas regiões culturais. Você nunca deve considerar certo, por exemplo, que a formatação de horas

Page 55: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

55

e datas em um determinada computador seja de um tipo. Os sistemas operacionais permitem umacompleta customização destes items, uma vez que precisam atender às mais diversas situaçõesculturais. Pode parecer tolo mas, caso um aplicativo desconsidere estas observações, em determinadascondições ele pode se tornar inoperável.

Suponha, por exemplo, uma instalação do sistema operacional Windows para a linguagem japosesa,árabe ou hebraica. Nestes contextos culturais, os calendários são expressos de forma muito diferentesdas mais conhecidas em um contexto cultural ocidental. Você não pode considerar previamente que oano possua 12 meses ou mesmo que o dia possua 24 horas. É justamente pensando nestas questõesque as API’s dos sistemas operacionais oferecem uma grande quantidade de rotinas que permitem-lheentender como tratar datas e horas em um computador.

Felizmente, o Object Pascal encapsula estas rotinas em interfaces de unidade de código de fácilmanipulação, bem como tratam grande parte dos problemas de conversões e adaptações de maneiraautomática.

Neste tópico você conhecerá o suporte ao trabalho com datas e horas oferecido pelo Object Pascal.

Dias, meses, anos...

O Object Pascal oferece muitos métodos de trabalho com dados que contêm datas. A classefundamental para o trabalho om datas é TDateTime que, além da data, armazena também horas,minutos e segundos. Contudo, existem classes específicas para manipulação de horas e datasseparadamente. A classe TTime manipulada dados referente a horas, enquanto TDate trabalhaexclusivamente com datas. Existem ainda muitas funções e procedimentos que permitem-lhe fazerpraticamente qualquer coisa razoável com datas e horas. A tabela abaixo lista algumas destas rotinas eo seu significado.

Rotina DescriçãoCompareDate Indica a relação entre 2 porções de 2 valores TDateTime.CompareDateTime Indica a relação entre 2 valores TDateTimeCompareTime Indica a relação entre 2 porções de hora de 2 valores TDateTime.CurrentYear Retorna o ano corrente no calendário Gregoriano. O valor retornado é um número de quatro

dígitos.Date Retorna a data atual.Time Retorna a hora atual.Now Retorna a data e hora atuais.DateOf Retorna a data de um TDateTime.DateTimeToFileDate Converte um TDateTime para um tipo TimeStamp do sistema operacional.DateTimeToSystemTime Converte um TDateTime em um TSystemTime da API do Win32.DateTimeToTimeStamp Converte um TDateTime em um TTimeSTamp.DayOfTheMonth Retorna o número de dias de um determinado mês.DayOfTheWeek Retorna o número de dias de uma semana.DayOfTheYear Retorna o número de dias de um determinado ano.DayOfWeek Retorna o número de dias da semana de uma data especificada.DaysBetween Retorna o número de dias entre duas datas especificadas.DaysInAMonth Retorna o númerode meses de um determinado ano.DaysInAYear Retorna o número de dias de um determinado ano.DaySpan Retorna o número de dias entre 2 datas, incluindo frações de dias.DecodeDate Retorna o ano, mês e dia de uma data.DecodeDateDay Retorna o ano e dia de uma data.DecodeDateFully Retorna o ano, mês, dia e dias da semana de uma data.DecodeDateMonthWeek Retorna o ano, mês, semana do mês e dia da semana de uma data.DecodeDateTime Retorna ano, mês, dia, hora, minuto, segundo e milisegundos de uma data.DecodeDateWeek Retorna o ano, semana do ano e dia a semana de uma data.DecodeDayOfWeekInMonth Para uma determinada data, retorna o ano, mês, dia da semana e o dia do mês.DecodeTime Quebra um TDateTime em horas, minutos, segundos e milisegundos.EncodeDate Retorna um TDateTime que representa um determinado ano, mês e dia.

Page 56: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

56

EncodeDateDay Retorna um TDateTime que representa um determinado dia do ano para um determinado ano.EncodeDateMonthWeek Retorna um TDateTime que representa um dia de uma semana em um mês e anos específicos.EncodeDateTime Retorna um TDateTime que representa um ano, mês, dia, hora, minuto, segundo e milisegundo.EndOfADay Retorna um TDateTime que representa o último milisegundo de um determinado dia.EndOfAmonth Retorna um TDateTime que representa o último milisegundo do último dia de um mês.EndOfAWeek Retorna um TDateTime que representa o último milisegundo de dia de uma semana.EndOfAYear Retorna um TDateTime que representa o último milisegundo de um determinado ano.FormatDateTime Formata um TDateTime.HoursBetween Retorna o número de horas entre 2 TDateTime.HourSpan Retorna o número de horas (incluindo horas fracionárias) entre 2 TDateTime.IncAMonth Incrementa a data em um mês.IncDay Incrementa a data em um dia.IncHour Incrementa a data em uma hora.IncMiliSecond Incrementa a data em um milisegundo.IncMinute Incrementa a data em um minuto.IncSecond Incrementa a data em um segundo.IsValidDateTime Indica se os valores para ano, mês e dia especificam uma data válida.IsValidDateWeek Indica se um determinado ano, mês e dia da semana especificam uma data válida.IsValidTime Indica se uma determinada hora, minuto, segundo e milisegundo especificam uma data válida.IsLeapYear Indica se um ano especificado é um ano bissexto.

Embora a lista acima possa parecer muito extensa, ela é apenas uma amostra das rotinas disponíveispara trabalho com datas. Você pode obter uma lista completa consultando a ajuda do Delphi.

Interpretando horas

Vamos mostrar alguns exemplos do uso de algumas das rotinas mencionadas na tabela acima.Normalmente, você não precisa se preocupar com os detalhes mais profundos do trabalho com datas, anão ser que sua aplicação trabalhe massivamente com cálculos de datas e coisas semelhantes.

O procedimento DecodeDate pode ser usado quando você precisa saber qual o dia, mês ou ano deuma data. Por exemplo.

varDT: TDateTime;Dia, mes, ano: word;S: string;

Begin

Dt := Date;//Assinala a data de hoje para a variável DtDecodeDate(Dt, Ano, Mês, Dia);

Case Mês of1: s := ‘Janeiro’;2: s := ‘Fevereiro’;3: s := ‘Março’;4: s := ‘Abril’;5: s := ‘Maio’;6: s := ‘Junho’;7: s := ‘Julho’;8: s := ‘Agosto’;9: s := ‘Setembro’;

Page 57: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

57

10: s := ‘Outubro’;11: s := ‘Novembro’;12: s := ‘Dezembro’;end;ShowMessage(‘Nós estamos em ‘ + S + ‘!’);

end;

A função FormatDateTime retorna uma string contendo a formatação de datas usada no computadoratual.

ShowMessage(FormatDateTime('"The meeting is on " dddd, mmmm d, yyyy, " at" hh:mm AM/PM', Now + 0.125);

O exemplo acima exibirá uma caixa de mensagem exibindo uma mesnagem com a data especificadano formato indicado na string dddd, mmmm, yyyy, onde d = dia, m = mês e y = ano. Existem muitosoutros formatos válidos. Para uma listagem completa, consulte a ajuda do Delphi.

Page 58: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

58

CC AA PP ÍÍ TT UU LL OO 55 -- PP RR OO CC EE DD II MM EE NN TT OO SS EE FF UU NN ÇÇ ÕÕ EE SS

Este capítulo introduzirá a idéia de procedimentos e funções de aplicativos. Em Delphi, praticamentetodo o código que você escreve em seus aplicativos são inseridos no escopo de procedimentos oufunções. Você perceberá que o domínio das técnicas de criação destes recursos é fundamental para odesenvolvimento de aplicações, tanto no Windows quanto no Linux.

Procedimentos e funções também estão diretamente associados ao controle de fluxo de seusaplicativos, o que significa que podem, no meio de seu escopo, desviar a execução do aplicativo paraoutro ponto de seu código. Talvez a principal vantagem do uso de procedimentos e funções é que elestrabalham de forma a modularizar as aplicações. De fato, cada procedimento ou função podeimplementar uma funcionalidade completa em um aplicativo.

Você conhecerá também algumas técnicas de trabalho com procedimentos e funções, bem como adiferença essencial entre eles.

Page 59: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

59

Procedimentos e funções

Proecedimentos e funções podem ser definidos como “rotinas” executadas por um aplicativo. Estadefinição genérica pode parecer insuficiente, mas aproxima-nos da idéia real do seu significado. OObject Pascal trabalha com um procedimentos como uma rotina de execução definida dentro de umaunidade de código. Um procedimento possui um escopo, isto é, um corpo de código-fonte no quialvocê escreve seu código. O início deste escopo é definido pela palavra reservada begin, e encerradapor um end;.Tudo o que estiver dentro destes dois delimitadores está dentro do escopo doprocedimento.

No caso de funções, todas estas afirmações continuam válidas, mas existem diferenças reais entreprocedimentos e funções.

Diferenciando procedimentos e funções

A maior diferença existente entre procedimentos e funções se refere à utilidade de ambos. Enquantoum procedimento é uma rotina encerrada em sí mesma, uma função sempre deverá retornar um valor.No Object Pascal, este valor pode ser qualquer tipo de dado aceito, bem como uma classe ou objeto. Odiagrama abaixo exibe o esquema de comportamento básico dos procedimentos e funções:O dado retornado por uma função pode também ser nil, isto é, nada foi retornado. Os métodos das

classes no Object Pascal são constituídos de procedimentos e funções implementados pelos objetos.

Conhecendo procedimentos e funções

Como vimos, procedimentos (procedure) e funções (functions) são referidas coletivamente comorotinas e estão contidas em blocos que podem ser chamados em diferentes lugares em um programa.Uma funtion é uma rotina que retorna um valor quando é executada; uma procedure não retornaresultados.

Como as funções retornam um valor, podem ser usadas em expressões de assinalamento e operaçõestais como:

I := SomeFunction;

Chamadas de procedimentos podem ser usadas como rotinas completas; por exemplo:

Procedure Function

Dado

Page 60: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

60

DoSomething;

Os procedimentos e funções podem se chamar recursivamente.

Declarações de procedimentos

A declaração de um procedimento tem a seguinte forma:

procedure procedureName parameterList ;directiveslocalDeclarationsbeginstatementsend;

Onde procedureName é qualquer identificador válido; statements é uma sequência de rotinas que sãoexecutadas quando o procedimento é chamado e (parameterList), directives; e localDeclarations; sãoopcionais.

Aqui está um exemplo de uma declaração de procedimento:

procedure NumString(N:Integer;var S:string );varV:Integer;beginV :=Abs(N);S :='';repeatS :=Chr(V mod 10 +Ord('0'))+S;V :=V div 10;until V =0;if N <0 then S :='-'+S;end ;

Dada esta declaração você pode chamar o procedimento NunString.

Declarações de funções

A declaração de uma função é parecida com a de um procedimento, exceto que ela especifica um tipode retorno e o seu valor. Elas têm a seguinte forma:

function functionName parameterList :returnType directiveslocalDeclarationsbeginstatementsend;

Page 61: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

61

Onde functionName é qualquer identificador válido, returnType é qualquer tipo de dado, statements éuma sequência de rotinas que são executadas quando a função é chamada, e (parameterList),directives; , e locaDeclarations; são opcionais.

O bloco de rotina das funções é governado pelas mesmas regras que se aplicam aos procedimentos;em um desses blocos você pode declarar variáveis e outros identificadores. Adicionalmente o nome dafunção age como uma variável especial que armazena seu valor de retorno, como em uma variávelpré-definida Result. Por exemplo,

function WF:Integer;beginWF :=17;end ;

Defini uma função chamada WF, que não tem parâmetros e sempre retorna o valor inteiro 17. Estadeclaração é equivalente a:

function WF:Integer;beginResult :=17;end ;

Nota: você pode assinalar um valor para result ou para o nome da função repetidamente dentro de umbloco.

Embora possa ser dado qualquer nome (identificador) a um procedimento ou função, muitas vezesexistem padronizações interessantes de nomenclatura. As funções , devido ao fato de retornaremvalores, muitas vezes começam com a expressão get (como em getColor). Os procedimentos têmnomes que explicam as suas funcionalidades. Se agem de forma a gravar dados ou alterá-los dealguma forma, às vezes têm o nome precedido pelas expressões set ou do (como em setColor oudoColor).

Overloading de procedimentos e funções

Você pode declarar mais de uma rotina com o mesmo nome dentro de um mesmo escopo. Isto échamado overloading, o que significa uma indicação para o compilador da existência de outras rotinascom o mesmo nome. Isto só é possível se as rotinas com o mesmo nome tiverem uma lista deparametros diferentes. Considere as seguintes declarações:

function Divide(X,Y:Real):Real;overload ;beginResult :=X/Y;end ;function Divide(X,Y:Integer):Integer;overload ;beginResult :=X div Y;end ;

As duas declarações acima têm o nome Divide, mas exigem parametros de diferentes tipos. Ao chamarDivide o compilador determina qual função evocar, examinando a lista de parametros passados.

O recurso de Overloading exige a distinção pelo número de parametros ou os tipos de parametros.

Page 62: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

62

Assim os seguintes pares de declarações causam um erro de complilação:

function Cap(S:string ):string ;overload ;ƒprocedure Cap(va Str:string );overload ;ƒ

Mas as declarações seguintes são legais.

function Func(X:Real;Y:Integer):Real;overload ;ƒfunction Func(X:Integer;Y:Real):Real;overload ;ƒ

Valor padrão de parâmetros

Você pode expecificar valores padrões para parâmetros em procedimentos ou funções. Valores padrõessão permitidos apenas para tipos ordinais, e podem ser providos apenas como último parâmetro nadeclaração dos procedimentos ou funções. Por exemplo:

procedure FillArray(A:array of Integer;Value:Integer =0);

Onde o parametro Value já é previamente assinalado para 0. As seguintes chamadas para oprocedimento acima são equivalentes:

FillArray(MyArray);FillArray(MyArray,0);

Nota: não é possível declarar multiplos parâmetros com valor padrão.

Page 63: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

63

CC AA PP ÍÍ TT UU LL OO 66 -- OO BB JJ EE TT OO SS EE CC LL AA SS SS EE SS

Este capítulo nos introduzirá em conceitos importantes do Objetc Pascal e da programação orientada aobjetos, como classes, objetos, propriedades e ponteiros. Como o Object Pascal é uma linguagemestritamente orientada a objetos o conhecimento destes pontos é fundamental para o desenvolvimentode aplicativos.

Você conhecerá também alguns métodos e recursos de herança e polimorfismo que estão presentes aolongo de toda a hierarquia de classes e objetos disponível com o Delphi.

Page 64: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

64

Tipo de Classe (class type )

Uma classe (class), ou class type, define uma estrutura composta de campos (fields), métodos(methods) e propriedades (properties). Instâncias de um class type são chamados objetos. Os campos,métodos e properiedades de uma classe são chamados seus componentes ou membros.

Campos de tipos

Um campo é essencialmente uma variável que é parte de um objeto. Como os campos de um record,os campos de uma classe representam dados que existem em cada instância da classe.Um método é um procedimento ou função associado com uma classe. Muitos métodos operam sobreobjetos, isto é, instâncias de uma classe. Alguns métodos (chamados métodos de classes) operamsobre os tipos de classes mesmo.Uma propriedade é uma interface para um dado associado com um objeto (freqüentementearmazenado em um campo). As propriedades têm especificadores de acesso, que determinam comoseus dados são lidos e modificados. De outras partes de um programa – fora do objeto em sí – umapropriedade aparece em muitos casos como um campo.Os objetos são dinamicamente alocados blocos de memória cuja estrutura é determinada por seustipos de classe (class type). Cada objeto tem uma única cópia de todos campos definidos na classe,mas todas as instâncias de um classe compartilham os mesmos métodos. Os objetos são criados edestruídos por métodos especiais chamados contrutores (constructors) e destruidores (destructors).Uma variável de um tipo de classe é atualmente um ponteiro que referencia um objeto. Assim, mais deuma variável podem referenciar o mesmo objeto. Como outros ponteiros, variáveis de class type podemconter o valor nil. Mas você não precisa explicitamente desreferenciar uma variável de tipo de classepara acessar o objeto para o qual aponta. Por exemplo:

SomeObject.Size := 100

Assinala o valor 100 para a propriedade size do objeto referenciado po SomeObject.

Um tipo de classe deve ser declarado e recebido um nome antes que ele possa ser instanciado. Declareclasses apenas em seções de escopo global de um programa ou unidade, não em declarações deprocedimentos e funções. Uma declaração de um tipo de classe tem a seguinte forma:

type className = class (ancestorClass)memberListend;

onde className é qualquer identificador válido, ascestorClass é opcional e se refere à classe da qualClassName é derivada e memberList declara membros, isto é, campos, métodos e propriedades daclasse. Se você omitir AncestorClass, a nova classe herda diretamente da classe Tobjetc. Se você incluiAncestorClass e memberList está vazio, você pode omitir o end. Uma declaração de tipo de classe podetambém incluir uma lista de interfaces implementadas pela classe.Os métodos aparecem na declaração da classe como cabeçalhos de funções e procedimentos semqualquer corpo. Por exemplo, veja a declaração da classe TmemoryStream, encontrada na unidadeClasses.pas.

typeTMemoryStream = class(TCustomMemoryStream)

private

Page 65: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

65

FCapacity: Longint;procedure SetCapacity(NewCapacity: Longint);

protectedfunction Realloc(var NewCapacity: Longint): Pointer; virtual;property Capacity: Longint read FCapacity write SetCapacity;

publicdestructor Destroy; override;procedure Clear;procedure LoadFromStream(Stream: TStream);procedure LoadFromFile(const FileName: string);procedure SetSize(NewSize: Longint); override;function Write(const Buffer; Count: Longint): Longint; override;end;

TmemorySTream descende de Tstream, herdando muitos de seus membros. Mas ele define (ouredefine) muitos métodos e propriedades, incluindo seu método destruidor Destroy. Seu métodoconstrutor, Create, é herdado, sem alterações, de Tobject e, assim, não é redeclarado. Dada estadeclaração, você pode criar uma instância de TmemorySTream da seguinte forma:

var stream: TMemoryStream; stream := TMemoryStream.Create;

Herança e escopo

Quando você declara uma classe, é posívl especificar seu ancestral imediato. Por exemplo:

type TSomeControl = class(TControl);

declara uma classe chamada TSomeControl que descende de TControl. Um tipo de classeautomaticamente herda todos os membros de seu ancestral imediato. Cada classe pode declarar novosmembros e pode redefinir outros herdados, mas uma classe não pode remover membros definidos emseu ancestral.O escopo de um identificador de um membro inicia no ponto onde o membro é declarado e continuaaté o final da declaração da classe.

TObject e TClass

A classe Tobject, declarada na unidade System.pas, é o último ancestral de todas as outras classes.Tobject denine apenas alguns métodos, incluindo contrutores e destruidores básicos. Adicionalmente aTobjetc, podemos encontrar declarado na mesma unidade a classe Tclass

TClass:TClass = class of TObject;

Para mais nformações sobre Tobject, consulte a ajuda on-line.

Page 66: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

66

Compatibilidade de tipos de classes

Um tipo de classe é compatível em termos de atribuição com seu ancestral. Isto significa que umavariável de um tipo de classe pode referenciar uma instância de qualquer tipo descendente. Porexemplo, dadas as seguintes declarações:

typeTFigure = class(TObject);TRectangle = class(TFigure);TSquare = class(TRectangle);

varFig: TFigure;

A variável Fig pode ser atribuída valores dos tipos Tfigure, Trectangle e Tsquare.

Tipos de objetos (Object Type )

Como uma laternativa para tipos de classes, você pode declarar tipos de objetos usando a sintax:

type objectTypeName = object (ancestorObjectType)memberListend;

onde ObjectTypeName é qualquer identificador válido, ancestorObjectType é opcional e MemberListdeclara campos, métodos e propriedades. Se ancestorObjectType é omitido, então o novo tipo não temqualquer ancestral. Object Types não podem ter membros publicados. Uma vez que Object Types nãodescendem de Tobject, eles não providenciam qualquer mecanismo construtor, destruidor ou métodos,o que lhe obriga a criar e destruir instâncias de um objetc type usando o procedimento New e Dipose,respectivamente.

Nota: Objetc Types são suportados apenas por compatibilidade com códigos pascal antigos. Seu usonão é recomendado no ambiente Delphi atual.

Visibilidade de membros de classes

Todo membro de uma classe tem um atributo chamado “visibilidade”, que é indicado por uma daspalavras reservadas private, protected, public, published ou automated. Por exemplo:

published property Color: TColor read GetColor write SetColor;

declara uma propriedade publicada chamada Color. A visibilidade determina onde e como um membropode ser acessado, com private representando o menor acessibilidade, protected representando umnível intermediário de acessibilidade e public, published e automated representando a maioracessibilidade.Se uma declaração de membro aparece sem seu próprio especificador de visibilidade, terá a mesmavisibilidade do membro que o precede. Membros declarados no início da declaração de classe têmespecificador de visibilidade published como padrão.

Page 67: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

67

Para facilitar a leitura do código, é melhor organizar a declaração de visibilidade colocando todos osmembros após os seus respectivos especificadores de visibilidade. Assim, uma declaração de classetípica deveria parecer-se com o código abaixo:

typeTMyClass = class(TControl)

private { private declarations here}

protected { protected declarations here }

public { public declarations here }

published { published declarations here }end;

Você pode aumentar a visibilidade de um membro em uma classe descendente ao redeclará-lo, masnão pode diminuir sua visibilidade. Por exemplo, uma propriedade definida como protected pode serfeita public em um descendente, mas não private. Não obstante, membros definidos como publishedpodem se tornar public em uma classe descendente.

Membros private , protected e public

Um membro definido como private é invisível fora da unidade ou programa onde sua classe édeclarada. Em outras palavras, um método private não pode ser chamado de outro módulo e umcampo ou propriedade private não podem ser lidos ou escritos a partir de outro módulo.

Um membro definido como protected é visível em qualquer lugar do módulo onde a classe édeclarada e também para classes descendentes. EM outras palavras, um método protected pode serchamado ou propriedades e campos lidos ou escritos, a partir da definição de qualquer método aolongo da classe que descende daquela para a qual o membro protected é declarado. Membrosdeclarados apenas para uso na implementação de classes derivadas são usualmente declarados comoprotected.

Um membro definido como public é visível onde quer que sua classe seja referenciada.

Membros published

Membros declarados como published têm a mesma visibilidade que aqueles declarados como public. Adiferença entre eles é que a Runtime Type Information (RTTI) é gerada para membros definidos comopublished. A RTTI é usada para acessar valores e propriedades de um objeto aosalvar ou carregararquivos de formulários, exibir propriedades no Object Inspector e outras funções.Todos os métodos são “publicáveis”, mas uma classe não pode publicar dois ou mais métodossobrescritos (overloading) com o mesmo nome. Os campos só podem ser publicados se forem de umaclasse ou tipo interface.Você define um membro como published quando deseja que o desenvolvedor o manipule diretamentena IDE do Delphi, assim como em tempo de execução.

Page 68: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

68

Membros automated 1

Membros definidos como automated têm a mesma visibilidade que os definidos como public. Adiferença é que a Automation type information (requerida para servidores Automation) é gerada paraos membros automated. Membros automated tipicamente aparecem apenas em classes exclusivas daprogramação para Windows, e não são recomendados para a programação Linux. As seguintesrestrições se aplicam a métodos e propriedades declaradas como automated:

• Os tipos de todas as propriedades, parâmetros de array, parâmetros de método e resultado defunções devem ser compatíveis com os tipos de dados suportados por Automation. Estes tipos são:Byte, Currency, Real, Double, Longint, Integer, Single, Smallint, AnsiString, WideString, TdateTime,Variant, OleVariant, WordBool e todos os tipos interface.

• Declarações de métodos devem usar a convenção padrão de chamada Register. Elas podem servirtuais, mas não dinâmicas.

• A declaração de propriedades podem incluir especificadores de acesso (read e write) mas outrosespecificadors (index, stored, default, nodefault) não são permitidos. Os especificadores de acessodevem listar um identificador de método que use a convenção de chamada register.Identificadores de campos não são permitidos.

• As declarações de propriedades devem especificar um tipo. Override de propriedades não épermitido.

A declaração de um método ou propriedade automated pode incluir uma diretiva dispid. No Windows,esta diretiva deve ser seguida de uma constante inteira que especifica um identificador (ID) dedespacho Automation para o membro. Do contrárion o compilador automaticamente assinala o ID deum mebro como um maior do que o maior ID usado por qualquer método ou propriedade na classe ouseus ancestrais.

Campos

Um campo é como uma variável de um objeto. Os campos podem ser de qualquer tipo, incluindo tiposde classes; isto é, campos podem armazenar referências a outros objetos. É comum definir camposcomo private. Para definir um campo de uma classe, simplesmente declare o campo como você fariacom uma variável. Todas as declarações de campos devem ocorres antes de qualquer declaração depropriedade ou método. Por exemplo, a seguinte declaração cria uma classe chamada TNumber cujoúnico membro é um campo inteiro chamado Int:

type TNumber = classInt: Integer;end;

Métodos

Um método é um procedimento (procedure) ou função (function) associado a uma classe. Umachamada a um método especifica o objeto ou, se for um método de uma classe, uma classe. Porexemplo

SomeObject.Free 1 O estudo da tenologia COM e Automation será feita no segundo curso.

Page 69: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

69

Chama o método Free em SomeObject.

Declarações e implementações de métodos

Dentro de uma declaração de classe, os métodos aparecem como cabeçalhos de procedimentos efunções que trabalham como declarações forward. Em algum lugar após a declaração da classe, masdentro do mesmo módulo, cada método é implementado ao definir a sua declaração. Por exemplo,suponha que a declaração de TmyClass inclua um método cahamado DoSomething:

typeTMyClass = class(TObject)

procedure DoSomething;

end;//A defining declaration for DoSomething must occur later in the module:procedure TMyClass.DoSomething;begin//end;

Enquanto uma classe pode ser declarado em ambas seções interface ou implementation de umaunidade, a definição da declaração para um método de uma classe deve estar na seçãoimplementation.As declarações de métodos podem incluir diretivas especiais que não são usados com outras funções eprocedimentos. As diretivas devem aparecer apenas na declaração da classe, não na definição dadeclaração.Entre estas diretivas podemos citar: overload; asbtract; virtual; dynamic; override; stdcall.

Inherited

A palavra reservada inherited implementa uma regra especial relacionada a um contexto depolimorfismo. Ela pode ocorrer em definições de métodos, com ou sem identificadores após ele. SeInherited é seguida de um nome de um membro, representa uma chamada comum de um método ouum referência a uma propriedade ou campo. Como no exemplo:

inherited Create(...);

Quando após inherited não segie qualquer identificador, el e se refere ao método herdade xom o mesmo nome dométodo definido.O uso de Inherited e suas capacidades ocorre freqüentemente na implementação de métodos contrutores, que chamam inheritedcom os mesmos parâmetros que forma passados ao descendente.

Self

Dentro da implementação de um método, o identificador Self referencia o objeto no qual o método échamado. Por exemplo, segue abaixo a implementação do método Add de Tcollection.

Page 70: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

70

function TCollection.Add: TCollectionItem;beginResult := FItemClass.Create(Self);end;

O método Add chama o método Create na classe referenciado pelo campo FitemClass, que é sempreum descendente de TcollectionItem.Self é útil por uma série de razões. Por exemplo, um identificador de um membro declarado em umtipo de classe poderia ser redeclarado no bloco de um dos métodos da classe. Neste caso, é possívelacessar o identificador do membro original como

Self.Identifier

Tipos de métodos

Os métodos podem ser estáticos (static, o padrão), virtuais (virtual) ou dinâmicos (dynamic). Métodosvirtuais e dinâmicos podem ser sobrescritos e eles podem ser abstratos (abstract). Estas designaçõessão utilizadas quando uma variável de um tipo de classe armazena um valor de um tipo de classedescendente. Elas determinam que implementação é ativada quando o método é chamado.

Métodos estáticos

Os métodos são, por padrão, estáticos. Quando um método estátivo é chamado, o tipo declarado deuma classe ou variável de objeto usada na chamada do método determina que implementação éativada. No exemplo seguinte, os métodos Draw são estáticos:

typeTFigure = classprocedure Draw;end;TRectangle = class(TFigure)procedure Draw;end;

Dadas estas declarações, o código abaixo ilustra o efeito da chamada de um método estático. Nasegunda cahamada para Figure.Draw, a variável Figure referencia um objeto da classe TRectangle,mas a chamada invoca a implementação de Draw em TFigure, pois o tipo declarado de Figure éTFigure.

varFigure: TFigure;Rectangle: TRectangle;beginFigure := TFigure.Create;Figure.Draw; // calls TFigure.DrawFigure.Destroy;Figure := TRectangle.Create;Figure.Draw; // calls TFigure.Draw

Page 71: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

71

TRectangle(Figure).Draw; // calls TRectangle.DrawFigure.Destroy;Rectangle := TRectangle.Create;Rectangle.Draw; // calls TRectangle.DrawRectangle.Destroy;end;

Métodos virtuais

Métodos virtuais são chamados da mesma forma que os métodos estáticos, mas, como os métodosvirtuais podem ser modificados, o compilador não sabe o endereço de uma função virtual em articularquando você a chama em seu código. Por isso, o compilador constrói uma Virtua Method Table (VMT),que fornece um meio para pesquisar endereços de funções em tempo de execução. A VMT de umobjeto contém todos os métodos virtuais de seus ancestrais, bem como os que ele mesmo declara; poresta razão, os métodos virtuais usam mais memória do que os dinâmicos, embora sejam executadoscom mais rapidez. Veja abaixo um exemplo de declaração de um método virtual:

procedure MetodoVirtual; virtual;

Métodos dinâmicos

Os métodos dinâmicos são, basicamente, métodos virtuais com um sistema de despacho diferente. Ocompilador atribui um número exclusivo a cada método dinâmico e usa estes números, juntamentecom o endereço de memória do método, para construir uma Dynamic Method Table (DMT). Aocontrário da VMT, a DMT de um objeto contém apenas os métodos dinâmicos que declara. Por isso, osmétodos dinâmicos fazem uso menos intensivo de memória do que os métodos virtuais, mas eles sãomais demorados de se chamar, pois você pode Ter que propagar através de várias DMT’s ancestraisantes de encontrar o endereço de um método dinâmico em particular.

Tanto os métodos virtuais como os dinâmicos são usados para oferecer suporte às tecnologias COM eOLE da Microsoft. Procedimentos de objetos COM (como os de um controle ActiveX, por exemplo)fazem uso comum de variants e métodos dinâmicos como mecanismo de linking remoto de umaplicativo cliente com algum recurso oferecido por um aplicativo servidor que não é conhecido duranteo processo de compilação de seu aplicativo.

Page 72: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

72

CC AA PP ÍÍ TT UU LL OO 77 -- CC OO NN HH EE CC EE NN DD OO AA VV CC LL EE AA CC LL XX

Tradicionalmente, o Delphi vem colocando à disposição dos programadores uma grande quantidade declasses e componentes presentes em bibliotecas de componentes, particularmente a Visual ComponentLibrary (VCL) que acompanha o Delphi desde sua primeira versão. Ao longo dos anos a VCL foiimensamente incrementada não só pelos novos componentes e classes inseridos pela Borland em novasversões do Delphi mas, principalmente, pela gigantesca produção de componentes e bibliotecas inteirasdesenvolvidos por diversos desenvolvedores em todo o mundo.Com o lançamento do Delphi 6, a Borland colocou à disposição dos desenvolvedores uma novabiblioteca de componentes denominada Component Library for Cross-Platform (CLX), cuja característicaprincipal é a portabilidade entre plataformas. Ou seja, um aplicativo desenvolvido sob a base CLXpossui código-fonte compatível com as plataformas Windows e Linux.

Neste capítulo estudaremos a estrutura da VCL e da CLX, assim como seus componentes centrais, ecomo você pode gerar aplicativos completamente portáveis do mundo Windows para o Linux ou destepara o mundo Windows.

Page 73: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

73

Bibliotecas de classes no Delphi 6

Tradicionalmente, o Delphi vem colocando à disposição dos programadores uma biblioteca decomponentes conhecida como Visual Component Library (VCL), onde se pode encontrar todos osobjetos e classes disponíveis para manipulação e construção dos mais diversos tipos de aplicativos.Embora o nome da VCL indique o contrário, a maioria dos objetos e classes contidos na VCL não sãopropriamente visuais, mas existe também uma grande quantidade deles que o são. Toda a VCL éconstituída sob a base de herança de TObjetc, o que quer dizer que não existem classes que nãoderivem de alguma forma de TObjetc.Para entender bem o que seja a VCL é preciso que compreendamos os seguintes pontos:

• A VCL é uma biblioteca hierárquica de componentes e classes, o que quer dizer que todos osseus elementos estão dispostos dentro de uma estrutura de herança e derivação estritamenteorientado a objetos.

• A VCL possui uma estrutura altamente expansível, ou seja, qualquer programador Delphi podecriar novos objetos ou mesmo bibliotecas inteiras de objetos que são inseridos no contextogeral da VCL. Uma vez isto feito, estes novos objetos estão já disponíveis para servirem declasses ascendentes de novos objetos que forem criadas.

• A VCL é uma biblioteca intrinsecamente ligada à plataforma Windows, encapsulando muitosdos objetos comuns disponíveis em dll’s como CommCtrl.dll e OleAut32.dll.

O Delphi 6 tornou disponível aos programadores uma inteiramente nova biblioteca de componentesconhecida como CLX. Como o próprio nome indica, a característica mais marcante da biblioteca CLX éa portabilidade entre as plataformas Windows e Linux. Esta novidade trouxe muitas mudanças e novasperspectivas para os programadores Delphi que viram, assim, um novo conjunto de possibilidades nodesenvolvimento de aplicativos.

Conhecendo a VCL

A Visual Component Library (VCL) deve ser usada toda vez que você desejar criar uma aplicativoWin32. Grande parte dos objetos presentes na VCL são construídos através de chamadas a rotinas daAPI do Win32, como é o caso de TToolBar, TCoolBar, TToolButton, TButton, TRadioButton etc. Istopossibilita uma grande compatibilidade entre seus sistemas e novas versões do sistema operacional.Uma vez que alterações nas rotinas da API (como, por exemplo, novos comportamentos de menus ebotões no Windows XP) são automaticamente “aceitas” pelos componentes de seu aplicativo. Contudo,você precisa estar consciente de que a VCL não oferece qualquer portabilidade para a plataformaLinux, ainda que grande parte do código de seu aplicativo VCL possa ser aproveitado sem alteraçõesem uma aplicativo que trabalhe com a CLX.

A VCL foi projetada com a finalidade específica de proporcionar o trabalho dentro de um ambientevisual. Em vez de criar uma janela e adicionar seu comportamento no código, você pode modificar ascaracterísticas comportamentais e visuais dos componentes à medida que elabora o programavisialmente. No Delphi 6 você inicia um novo aplicativo VCL ao selecionar “File | New | Application”, emuitos recursos disponíveis no Object Repository são exclusivo de aplicações VCL. Isto se explica pelofato de não haver suporte no Linux a diversas tecnologias como objetos COM, Automation, MTS, COM+,CoolBars etc. Estas tecnologias são aplicáveis apenas ao mundo Linux.Devido ao fato de a VCL ser uma biblioteca completa e extensa, você pode estar certo de que não hánada na plataforma Windows que não possa ser feito com a manipulação de suas classes. Usando aVCL e o compilador Delphi você pode fazer coisas que vão de Fontes True Type a grandes sistemas debancos de dados remotos e, para citar novas tecnologias, objetos COM+, MTS e aplicativos .NET. Estaabrangência fez com que a própria Microsoft reconhecesse o Delphi como ferramenta “preferencial” nodesenvolvimento de soluções Windows, assinando acordos de troca de tecnologias (principalmente paraaplicações WEB) com a Borland.

Page 74: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

74

Quando você cria um novo componente ou classe você está, na verdade, adicionando-os à VCL atravésdos métodos de derivação de classes e herança de um dos objetos da hierarquia da VCL. A VCLpermite também que você altere as características de um componente ou classe já existente (desdeque você possua o código-fonte deles), o que trará automaticamente as mesmas mudanças em todasoutras classes que utilizem de alguma forma a classe alterada.

Classes raízes da VCL

A VCL possui algumas classes que são centrais em toda a hierarquia. Isto significa que estas classesimplementam tipos de objetos bastante diferentes dos seus ascendentes e serve muitas vezes de pontode partida para criação de muitos tipos de classes e componentes.Para esclarecer este aspecto, é preciso compreender alguns “tipos” de objetos existentes ao longo daVCL. Em termos gerais, podemos dizer que na VCL existem:

• Classes. São objetos não visuais que não podem ser considerados componentes e, portanto, nãosão instalados na Component Pallete. Exemplos de classes são TSTrings, TSTream, TRegistry emuitos outros.

• Componentes. São, no sentido exato da expressão, objetos não visuais que são instalados, masnão fazem parte da interface com o usuário de um aplicativo. Os exemplos mais típicos são classesque manipulam dados em um banco de dados, como TTable, TIBQuery ou TADOCommand.

• Controles. São componentes visuais que são usados na construção da interface com o usuário.Existem controles gráficos e controles com manipulador de janelas (Handle). Os primeiros sãousados como elementos importantes no desenho de uma janela, e os outos como elementos dainterface que possibilitam entrada (input) de dados do usuário via teclado, mouse ou outrodispositivo.

Esta classificação indica-nos que componentes, na verdade, são os descendentes da classeTComponent em diante (componentes e controles), ainda que se use este termos de forma bastantegeneralizada. Veja abaixo um diagrama extremamente simplificado da estrutura central da VCL.

TObject

A classe TObject é o descendente último de todas as outras classes e componentes presentes na VCL.Isto significa que é impossível você criar uma classe que não descenda (em última instância) deTObject. Conseqüentemente todas as outras classes e componentes herdam as propriedades e métodosdefinidos para TObject que são:

Propriedades DescriçãoName Fornece o nome da instância da classe ou objetoTag Valor inteiro para uso geral

Métodos DescriçãoCreate Fornece mecanismos gerais de instanciação do objetoFree Implementa um mecanismo geral de destruição do objeto instanciado.

Page 75: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

75

TPersistent

Como se pode observar do diagrama acima, TPersistent descende diretamente de TObject. Acaracterística principal de TPersistent é que esta classe implementa controle sobre leitura e escrita desuas propriedades em e para um fluxo. Como todos os componentes são descendentes de TPersistent,suas propriedades se beneficiam desta característica. TPersistent define também alguns métodosprincipalmente para criadores de componentes.A tabela abaixo relaciona alguns destes métodos:

Método FuncionalidadeAssign Permite que um componente atribua a si mesmo os dados associados a outro componente.AssignTo Este método protegido é onde os descendentes de TPersistent devem implementar a definição da

VCL para AssignTo. TPersistent, por si só, produz uma exceção quando este método é chamado.AssignTo é onde um componente pode atribuir seus valores de dados para outra classe ou instâmcia– o oposto de Assign.

DefineProperties Permite aos criadores de componentes definir o modo como um componente armazena suaspropriedades extras ou não-publicadas. É geralmente usado para fornecer um meio para umcomponente armazenar dados que não sejam de um tipo simples como, por exemplo, dados binários.

TComponent

Esta classe descende diretamente de TPersistent. TComponente implementa recursos especiais quepermitem a manipulação de um objeto de uma classe que descenda dele em tempo de projeto, apartir do Object Inspector. Ou seja, os descendentes de TComponent podem ser manipulados durantea fase de projeto assim como podem ser instalados na palheta de componentes. TComponent definemuitos novos métodos e propriedades. Entre eles, citamos:

Propriedade FuncionalidadeOwner Indica o propriedtário do componente.ComponentCount Armazena o número de componentes que o componente possui.ComponentIndex Indica a posição do componente na lista de componentes que o componente possui.Components Um array contendo os componentes possuídos pelo componente.

Método FuncionalidadeFindComponent Usado para encontrar (fazer referência) a um componente pelo seu nome.GetParentComponent Retorna a instância do componente que possui o componente atual. Se não houver nenhum,

retorna nil.HasParent Indica de o componente é possuído por algum outro componente.

No fragmento de código que segue, ilustramos o uso de alguns destes recursos:

varCheck: TcheckBox;

beginCheck := FindComponent(‘CheckFinaliza’);if Check <> nil then beginIf Check.HasParent then Check.Checked := True;

If Check.Checked then Application.Terminate;

Page 76: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

76

End;End;

A varável Check (do tipo TCheckBox) é atribuída a um componente chamado “CheckFinaliza”. Se estecomponente é encontrado (<> nil), processa-se o seguinte:

Se ele for contido por outro componente (HasParent), atribui True à sua propriedade Checked;Se a propriedade Checked for True, finaliza o aplicativo (Application.Terminate).

Este código é apenas uma ilustração, e pode parecer não possuir muito sentido prático, mas, dequalquer forma, exibe o uso de alguns métodos implementados em TComponent.

TControl

A classe TControl implementa muitos recursos responsáveis por “tornar” um componente visual. Porexemplo, TControl introduz a capacidade do componente exibir a si mesmo, propriedades deposicionamento como Left, Top, propriedades que definem o seu tamanho como Heigth e Width emuitas outras propriedades. TControl também introduz propriedades relacionados à visibilidade,disponibilidade e aparência como Visible, Enabled e Color ou inserção de texto o controle como Captione Text. Outros recursos marcantes implementados com Tcontrol é a capacidade dos componentesderivados desta classe responderem a interações como o mouse, através dos eventos OnMouseMove,OnMouseEnter, OnMouseUp, OnMouseDown, OnClick; OnDblClick etc.A maioria dos controles descende de um dos dois descendentes diretos de TControl: TGraphicControl eTWinControl.

TWinControl

Os controles padrão do Windows descendem de TWinControl. Estes controles padrão são objetos quevocê pode ver na maioria das aplicações do Windows, tais como caixas de edição, botÕes, caixas decombinação, caixas de listagem etc. O Delphi encapsula o comportamento destes controles do Windowsem objetos, e não manipula-os diretamente através de chamadas da API do Windows.Os descendentes de TWinControl possuem algumas características que os distingue de outroscomponentes:

• Possuem uma alça (um handle) de janela na memória;• Podem receber foco de entrada através do mouse, teclado ou outro dispositivo;• Podem ser pais (conter) de outros componentes.

TWinControl implementa diversas funcionalidades referentes a manipulação de alças de janelas (comoem muitas chamadas à API do Windows), entrada e saída de foco de input, bem como aparência docontrole. Como programador de aplicações, você usará largamente os descendentes de TWinControlem seus aplicativos.

TGraphicCotrol

Os descendentes de TGraphicControl são controles visuais, porém possuem diferenças marcantes secomparados aos descendentes de TWinControl:

Page 77: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

77

• Não possuem um a alça de janela do Windows;• Não podem receber o foco de entrada;• Não podem conter outros componentes

Descendentes de TGraphicControl devem ser usados sempre que você deseja exibir algo ao usuárioque não exija um comportamento de entrada de dados. Um exemplo comum são imagens ou controlesque forneçam bordas diferenciadas em uma janela. Como descendentes de TGraphicControl nãopossuem manipuladores de alça de janela, eles consomem menos recursos do que os controles quepossuem esta característica. Além do mais, o processo de pintura do controle é bem mais rápido doque o de outro descendente de TWinControl. Finalmente, os descendentes de TGraphicControl podemresponder a mensagens de dispositivo de mouse.

Classes de manipulação de exceções

A VCL também introduz um conjunto de classes especiais destinadas exclusivamente à manipulação deexceções em aplicativos. Exception é um descendente direto de TObject e implementa os recursos maisgerais de interceptação de exceções.Você não deveria usar a classe Exception em seus aplicativos, mas sim as classes que dele descendem,uma vez que possuem características mais específicas para manipular tipos particulares de exceções.Por exemplo. A exceção gerada pela falta de memória para executar um procedimento é diferentedaquela causada pela referência a um índice inexistente em uma lista de strings. Conseqüentemente, écerto que precisaríamos manipular cada uma destas exceções de forma diferenciada. Para isto, a VCLdesenvolveu uma grande quantidade de classes de exceções, além de permitir que você mesmo definasuas próprias classes de exceções. Na grade abaixo são listadas algumas das mais importantes classesde exceções e suas respectivas funcionalidades.

Classe DescriçãoEAcessViolation Classe de exceção para erros de acesso inválido de memória.EOutOfResources Classe de exceção para alocações de alças de janelas mal-sucedidasEOutOfMemory Classe de exceção para acesso a memória mal-sucedido.EExternal Classe que captura exceções em registros (records) do Windows.EMathError Classe-base para manipulação de erros matemáticos com números de ponto flutuante.EIntError Classe-base para erros com números inteiros.EPrivilege Classe de exceção para manipulação de violação de privilégios do WindowsEControlC Classe usada para manipular falhas no término de aplicativos console ao pressionar-se

as teclas Ctrl+C.EConvertError Classe de manipulação de exceções em conversões de strings e objetos.EConversionError Classe de manipulação de exceções em erros de conversão de medidas.EDatabaseError Classe de exceção para erros em bancos de dados.EDateTimeError Classe de exceção para entradas inválidas de datas/hora.EDBClient Classe de exceção para erros em client datasets.EDBEngineError Classe de exceção para erros do Borland Database Engine (BDE).EDivByZero Classe de exceção para erros de divisão de inteiros por zero.ERangeError Classe de exceção para valores inteiros que são muito grandes para o tipo declarado

ao qual são atribuídos.EDOMParseError Classe de exceção de erros que ocorrem quando uma implementação DOM é vinculada

a um documentos XML.EFCreateError Classe de exceção para erros na criação de arquivos de stream.EFOpenError Classe de exceção para erros que ocorrem quando um arquivo de stream é aberto.EInvalidGraphic Classe de exceção para tipos de arquivos gráficos não-conhecidos.EInvalidGraphicOperation Classe de exceção para operações inválidas com objetos gráficos.EInvalidGridOperation Classe de exceção para operações inválidas com grades.EInvalidPointer Classe de exceções para operações inválidas com ponteiros.EListError Classe de exceção para erros em listas e strings.EMCIDeviceError Classe de exceção para dispositivos que provêem um driver de MCI (Media Control

Interface).EMenuError Classe de exceção envolvendo items de menus.

Page 78: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

78

EOleCtrlError Classe de exceção para erros em controles ActiveX.EOleError Clase de exceção para manipulação de erros OLE de baixo nível.EOleSysError Classe de exceção para erros específicos de uma interface OLE Idispatch.EOleRegistrationError Classe de exceção para erros que ocorrem durante o registro de um objeto OLE.EOSError Classe para manipulação de erros do sistema operacional.EPrinter Classe de excecção para erros de impressão.EReconcileError Classe de exceção para erros de atualização de client datasets.EUpdateError Classe de exceção para erros de atualização de um dataset provider.EWebBrokerException Classe de exceção disparadas por objetos WebBroker.EAbstractError Classe de exceção para erros de chamadas a métodos abstratos.EADOError Classe de exceção para erros de banco de dados gerados por fontes de dados ADO.EIBErrror Classe de exceção para erros em bancos de dados InterbaseESocketConnectionError Classe de exceção para erros que surgem quando do envoi ou recebimento de

mensagens usando TSocketConnection.EXMLDocError Classe de exceção para erros de edição ou parsing em um documento XML.EDBEditError Classe de exceção para erros de dados que são incompatíveis com uma determinada

máscara.

Esta lista, apesar de ser um pouco extensa, está muito longe de ser completa. Para uma referênciacompleta, consulte a ajuda on-line e o mapa de classes da VCL distribuídos com o Delphi 6.

Conhecendo a CLX

A Component Library for Cross-Platform (CLX) é uma biblioteca hierárquica de componentesdesenvolvida para uso no Delphi 6 e no Kylix. Analisando sob uma perspectiva genérica, a CLX possuiuma estrutura muito similar à VCL, sendo contruída igualmente sob o fundamento de TObject e asclasses raízes presentes na VCl. Neste tópico estudaremos as principais características da CLX e comovocê poderá usa-la para desenvolver aplicativos automaticamente portáveis entre a plataforma Win32 eLinux.

Obtendo compatibilidade entre Delphi e Kylix

A biblioteca CLX é o elemento essencial que promove a total compatibilidade entre o Delphi 6 e o Kylix.Esta compatibilidade existe em três níveis distintos:

• A linguagem Object Pascal usada nos dois ambientes;• A biblioteca de componentes CLX;• A IDE dos 2 ambientes de desenvolvimento.

A linguagem Object Pascal usada pelo Delphi é exatamente a mesma que o ambiente Kylix utiliza. Istotorna os programadores Delphi automaticamente aptos para a programação para a plataforma Linuxcom o Kylix. As diferenças existentes no Object Pascal disponível no Delphi e no Kylix se referemunicamente aos recursos implementados na VCL que são exclusivos para a programação Windows.Veremos adiante os detalhes desta diferença.

A CLX é realmente o grande “cimento” que une a programação visual do Delphi e do Kylix. Se vocêdesenvolver no Delphi um aplicativo CLX, ele será 100% compatível (o que quer dizer também“compilável”) com o ambiente Kylix. O mesmo código CLX poderá ser compilado sem quaisqueralterações tanto no Delphi (gerando aplicativos Windows) como também no Kylix (gerando aplicativosLinux). Disto se pode concluir que o seu código-fonte é totalmente compatível com as 2 plataformas,mas os diversos tipos de executáveis e/ou serviços que você desenvolver estarão vinculados ao sistema

Page 79: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

79

Windows se forem resultado de uma compilação no Delphi ou, pelo contrário, estarão prontos para oLinux se os compilar no Kylix.

Amplo suporte ao desenvolvimento WEB e banco de dados

Uma das características mais fortes da CLX (que segue o exemplo da VCL) é o forte suporte aodesenvolvimento WEB que apresenta. De fato, ao lado dos mais diversos tipos de executáveis “comuns”que o ambiente Linux suporta, a CLX oferece suporte ao desenvolvimento de qualquer tipo deaplicações e serviços WEB disponíveis na plataforma Linux. E você pode ainda estar certo de obtercompatibilidade com o ambiente Windows também no desenvolvimento WEB.

A CLX também segue a tradição da VCL ao oferecer o mais amplo suporte a tecnologias e fontesvariadas de dados de bancos de dados. De fato, o Delphi desde já há muitos anos se destaca nesteponto quando comparado com as diversas ferramentas de desenvolvimento disponíveis no mercado. Aolongo dos anos, este destaque se tornou cada vez mais evidente e reconhecido pelos mais diversosfornecedores de tecnologia de banco de dados, como comprovam as consecutivas vitórias obtidas peloproduto em testes, concursos etc promovidos por inúmeras empresas em todo o mundo. A CLX ofereceatualmente suporte a qualquer tipo de banco de dados disponível no mundo Linux e usa 2 tecnologiasbásicas de acesso: a DBExpress e o Acesso nativo.Veremos com muitos detalhes em que consiste este suporte e um dos fundamentos maioresfundamentos da superioridade Delphi/Kylix no acesso a banco de dados: a arquitetura expansível deTDataset.

Diferenças tecnológicas básicas entre a VCL e a CLX

Todas as diferenças fundamentais existentes entre as bibliotecas CLX e VCL dizem respeito à ausênciade suporte para algumas tecnologias Windows na CLX. Como a CLX foi desenvolvida para oferecercompleta compatibilidade Delphi/Kylix, alguns recursos do mundo Windows que inexistem naplataforma Linux não encontram suporte na CLX, mas podem ser encontrados na VCL.Entre as diferenças básicas que podemos perceber ao analisar a estrutura e suporte da CLX comparadacom a VCL, podemos enumerar:

• Inexistência de suporte a tecnologias especificamente Windows como a Registry, tecnologia COM,ActiveX e seus muitos derivados.

• Inexistência de suporte para bancos de dados indisponíveis na plataforma Linux, como MSAcess,MSSQL Server e Visual FoxPro.

• Inexistência de suporte a tecnologias proprietárias Microsoft de acesso a banco de dados que usamCOM, como ODBC, DAO, OLEDB e ADO.

• Inexistência de suporte a tecnolgias Microsoft de serviços WEB baseadas no COM, como ASP.• Inexistência de componentes e controles construídos fortemente sob a arquitetura Win32.• Inexistência de suporte ao Borland Database Engine (BDE).

Como é visível na análise destes items, percebemos que todo o invejável suporte às mais diversastecnologias COM, existentes na VCL, simplesmente inexiste na CLX. E, até onde podemos entender,sempre será assim, uma vez que estas são tecnologias unicamente aplicáveis ao mundo Windows.Podemos ver também (e sempre devido às mesmas razões) que componentes construídos baseados emtecnologias Win32 não podem ser encontrados na CLX. Entre estes componentes, citamos aqui toda asérie de controles e componentes para geração de relatórios conhecidos comumente comoQuickReport. Para esclarecer ainda mais este ponto, suponha que você tenha criado um componentepara controle de acessos de usuários em uma rede de servidor de domínio Windows NT. Como seu

Page 80: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

80

componente certamente faz chamadas à API do NT, é lógico que ele não poderá ser incorporado à CLX.Ou ainda se você construiu uma biblioteca de componentes para acesso nativo à API do MS SQL server;é claro que não adianta tentar incorpora-los à CLX, pois seus componentes não encontrarão em umambiente Linux o conjunto de dll’s que fornecem a interface API para o gerenciador de banco dedados relacional da Microsoft.Quanto à BDE, ela foi completamente suplantada pela nova tecnologia DBExpress.

Page 81: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

81

CC AA PP ÍÍ TT UU LL OO 88 -- TT AA RR EE FF AA SS CC OO MM UU NN SS DD EE PP RR OO GG RR AA MM AA ÇÇ ÃÃ OO

Este capítulo discute o fundamental sobre algumas das tarefas mais comuns na programação emObject Pascal. Trabalhar com strings, listas de strings, tipos numéricos e arquivos são tarefas tãocomuns, que em praticamente qualquer aplicativo que fizer terá de exercitar esta prática. Da mesmaforma, você conhecerá de que forma pode construir um aplicativo gráfico típico, com menus e barrasde ferramentas. O Delphi oferece grande suporte ao desenvolvimento visual e, na verdade, você podeexecutar cada uma destas tarefas de maneiras bastante diferentes.Por exemplo, se desejar criar um menu principal em uma aplicação, terá de pensar inicialmente noobjeto a ser usado na construção de um menu; perceberá, então, que o Delphi lhe oferece mais deuma opção. Ou, em outro exemplo, terá de decidir que tipo de barra de ferramenta irá usar em suaaplicação etc.

Finalamente, você desenvolverá dois aplicativos funcionais que ilustram as tarefas mais comuns nacriação de um aplicativo GUI, tanto para a plataforma Windows, quanto para a Linux.

Page 82: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

82

Trabalhando com listas de strings

As aplicaçÕes freqúentemente precisam manipular listas de caracters (strings). Entre os exemplos deuso deste recurso podem citar o trabalho com grades, arquivos texto, informações internas doprograma, listas armazenadas em controles e muitas outras situações. O Object Pascal oferece umagrande variedade de procedimentos e funções para trabalhar com estas listas, além de classesespecíficas que armazenam listas de strings.

As classes Tstrings e TStringList

Tstrings e TStringList são classes fundamentais para o trabalho com listas de strings. Tstringsimplementa uma série de métodos abstratos para leitura, inserção, deleção etc de strings em uma listaindexada baseada em 0. Oferece também a capacidade para salvar esta lista em um arquivo texto,bem como abrir um arquivo com este mesmo formato. Você usa sempre TStrings quando utilizacontroles como TcomboBox, TMemo ou TlistBox em suas aplicações. Os desenvolvedores de aplicaçõesWEB também precisam manipular com freq:uencia instâncias de Tstrings. Alguns descendentes deTSTrings são capazes de armazenar uma lista extensa de caracteres em várias linhas. TstringList herdatodas as características de TSTrings, introduzindo novos métodos para ordenação de listas e controlede mudanças no conteúdo da lista.Você deve sempre criar a lista de strings antes de poder utilizá-la e, ao final do seu uso, destruí-la damemória. Isto é extremamente simples. Veja o exemplo abaixo:

var

StringList: TStrings;begin

StringList := TStringList.Create;//cria a lista try with StringList do begin Add('linha 1'); Add('linha 2');

end;

finally StringList.free;//destrói a lista de strings end;end;

Usando listas de strings com arquivos

Para carregar um arquivo texto em uma lista de strings, você pode usar os métodos LoadFromFile,passando como parâmetro o endereço do arquivo, a fim de que possa editá-lo ou simplesmente ler oseu conteúdo. Se desejar salvar as alterações feitas, use o método SaveToFile, passando também oendereço do arquivo no seu disco. Carrega a um arquivo na lista / Salva a lista em um arquivo

Ex:

procedure TForm1.FormCreate(Sender: TObject);

Page 83: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

83

var List: TStringList;begin List := TStringList.Create; Try List.LoadFromFile(‘c:\windows\Readme.txt’); List.Add('Estou escrevendo mais uma linha'); List.Add('E agora ainda outra linha'); ListBox1.SaveToFile(‘c:\windows\Novo arquivo.txt’);//salva em arquivo

end; finally List.Free; end;end;

Entre outras operações comumente feitas como lista de strings temos:

• Contagem de strings da lista• Acesso a uma string em particular• Encontrar e posionar uma string na lista• Adicionando uma string à lista• Movendo strings dentro da lista• Deletando strings da lista• Copiando uma lista completa de strings

Contando strings na lista

A propriedade somente leitura Count retorna o númeo de strings de uma lista. Uma vez que listas destrings usam índices baseados em 0, Count é um mais o índice da última string.

Acessando uma string em particular

A propriedade do tipo array chamada strings contém as strings da lista, referenciadas por um índicebaseado em 0. Como esta é a propriedade padrão em listas de strings você pode omitir o identificadorstrings quando for acessar a lista. Veja abaixo:

StringList1.Strings[0] := 'primeira string.';

É quivalente a

StringList1[0] := ' primeira string.';

Movendo uma string dentro da lista

Para mover uma sting dentro de uma lista, chame o método Move, passando 2 parâmetros: o índicecorrente da string e o índice para o qual você quer assinalá-la. Por exemplo:

Page 84: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

84

Move(2, 4)move a terceira string para a quinta posição na lista.

Deletando uma string da lista

Para deletar uma string da lista chame o método Delete, passando o índice da string a ser eliminadada lista. Se você não sabe o índice da string, use o métod IndexOf para localaizá-la. Se você quiserdeletar todas as strings da lista, chame o método ClearO exemplo abaixo usa IndexOf e Delete para encontrar e deletar a string:

with ListBox1.Items dobeginBIndex := IndexOf('bureaucracy');if BIndex > -1 thenDelete(BIndex);end;

Copiando uma lista completa de strings

Você pode usar o métod Assign para copiar strings de uma outra lista de strings, sobrescrevendo oconteúdo da lista que chamou o método. Para sinserir novas strings no final da lista, chame o métodoAppendSTrings. Por exemplo,

Memo1.Lines.Assign(ComboBox1.Items);

Copia a lista de um ComboBox para um objeto Memo (sobrescrevendo seu conteúdo); mas

Memo1.Lines.AddStrings(ComboBox1.Items); { appends strings to end }

Adiciona as linhas de umComboBox para o memo.

Manipulando Exceções

O Delphi provê um mecanismo para assegurar que as aplicações sejam robustas, isto é, manipulem oserros de uma maneira consistente. A manipulação de exceções permite a um aplicativo recuperar-se deerros sempre que possível, encerrando-os se necessário for, sem que ocorra perda de dados ourecursos. As condições de erros são chamadas Exceptions (exceções) que são classes derivadas deException, um objeto diretamente descendente de TObject.

Exceções e o controle de fluxo

O Object Pascal torna fácil a incorporação de manipuladores de exceções em seu aplicativo porque asexceções não exigem grandes alterações no controle de fluxo. Com efeito os manipuladores são

Page 85: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

85

inseridos na forma de blocos de código protegidos que você define para assegurar o funcionamentocorreto de uma determinada operação. O código seguinte inclui um bloco protegido que, caso ocorrauma exceção dispara o sinal de beep da CPU.

tryAssignFile(F, FileName);Reset(F);ƒexcepton Exception do Beep;end;ƒ { A execução encerra aqui. }

Try ... Finally

As palavra reservada Try indica o início de um bloco de código protegido. O código dentro do bloco éexecutado e, finalmente, executa o código após a palavra reservada Finally. A execução do blocoiniciando em Finally sempre ocorrerá, caso haja uma exceção ou não. Veja os exemplos abaixo

varS: string;Lista: TstringList;beginTryLista := TstringList.Create;Lista.Add(‘linha índice 0’);S := Lista.Strings[22]; //Aqui ocorrerá uma exceção

Finallyif Assigned(Lista) then Lista.Free;

end;end;

Neste caso tudo correu bem e o Lista foi devidamente destruída da memória após Finally.

varS: string;Lista: TstringList;

beginTryLista := TstringList.Create;Lista.Add(‘linha índice 0’);S := Lista.Strings[22]; //Aqui ocorrerá uma exceção

Finallyif Assigned(Lista) then Lista.Free;

end;end;

Page 86: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

86

Neste outro exemplo a execução sofrerá interrupção devido ao erro ao tentar acessar-se uma stringinexistente na lista. Contudo, o bloco protegido garantirá a destruição de Lista na memória. Sem esterecurso o aplicativo poderia estar deixando “lixo” na memória.Você deve usar a estrutura Try ... Finally quando desejar tratar exceções simples de forma silenciosa(sem emitir avisos ao usuário) , mas bastante segura.

Try ... Exception

É possível também escrever blocos protegidos usando uma estratégia mais explícita de tratamento deexceções. Em algumas situações será preciso interceptar e identificar o tipo de exceção, se ela forgerada. O bloco protegido Try ... Except garante que, se alguma exceção ocorrer, o código escrito apósa palavra reservada Except seja executado. Aí você deve realizar operações específicas como desalocarrecursos alocados e identificar a origem da exceção. Observe que o trecho de código escrito após apalavra reservada Exception só será executado se uma exceção ocorrer. Veja o exemplo abaixo:

varS: string;Lista: TstringList;beginTryLista := TstringList.Create;Lista.LoadFromFile(‘c:\Windows\Readme.txt’);Lista.Add(‘linha índice 0’);Lista.Free;

Lista.SaveToFile((‘c:\Windows\Readme.txt’); //Aqui ocorrerá uma exceção!Lista //foi já foi destruída

Exceptif Assigned(Lista) then Lista.Free;MessageDLg(‘Uma exceção ocorreu! Seu programa estáerrado.’,mtError,[mbOk],0);

end;end;

Ao tentar acessar Lista após a sua destruição, certamente ocorrerá um erro. O código escrito apósExcept será executado, desalocando recursos se necessário e emitindo um aviso de erro ao usuário.

Na verdade, o recurso de blocos protegidos é extremamente poderoso, e você vivenciará situações bemmais complexas quando ele lhe prestará grande auxílio.

Que tipo de recursos proteger?

Sob circunstâncias normais, você pode assegurar-se que uma aplicação irá liberar recursos alocatodosao incluir blocos protegidos durante a alocação, garantindo assim a desalocação. Quando uma exceçãoocorre, contudo, você precisa estar certo de que a aplicação ainda executa os recursos alocados.Alguns recursos comuns que você deveria sempre se assegurar de liberá-los são os seguintes:

• Arquivos

Page 87: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

87

• Memória• Recursos do Windows• Objetos

Por exemplo, o seguinte manipulador de eventos aloca memória e, em seguida, gera um erro, deforma que ele nunca poderá liberar a memória alocada.

procedure TForm1.Button1Click(Sender: TComponent);varAPointer: Pointer;AnInteger, ADividend: Integer;beginADividend := 0;GetMem(APointer, 1024);{ aloca 1K de memória}AnInteger := 10 div ADividend;{ Isto gera um error... }FreeMem(APointer, 1024);{ mas o aplicativo nunca chegará aqui }end;

Embora muitos erros não são óbvios, o exemplo ilustra um ponto importante: quandoa divisão por zeroocorre, o aplicativo não é capaz de liberar a memória antes alocada. Este código deveria ser escritousando blocos protegidos, da forma como segue:

procedure TForm1.Button1Click(Sender: TComponent);varAPointer: Pointer;AnInteger, ADividend: Integer;beginADividend := 0;TryGetMem(APointer, 1024);{ aloca 1K de memória}AnInteger := 10 div ADividend;{ Isto gera um error... }

FinallyFreeMem(APointer, 1024);{ mas o aplicativo nunca chegará aqui }end;

Manipulando classes de exceções

Devido ao fato de os objetos de exceções serem parte de uma hierarquia, você pode especificarmanipuladores para uma parte inteira da hierarquia ao prover um manipulador para uma classe deexceção a partir do qual a parte da hieraquia desejada descende. O seguinte bloco mostra um exemploespecífico de manipulação de todas exceções matemáticas relacionadas a números inteiros:

Try

.../Ocorre uma operação

Except

On EintError do //Manipula erros relacionados a números inteirosend;

Page 88: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

88

É possível ainda especificar manipulkadores para exceções ainda mais específicas, mas você precisacolocar estes manipuladores antes do manipulador genérico, pois a aplicação os procura na ordem emque são inseridos. Por exemplo, este bloco provê manipulação de erros específicas para erros de faixa(range) e outra para mnipular todos os erros matemáticos relacionados a números inteiros:

Try

.../Ocorre uma operação

Except On ErangeError do //faz alguma coisa neste caso On EIntError do //Manipula erros relacionados a números inteirosend;

Para uma referência completa sobre as classes de manipulação de erros existentes, consulte a ajudaon-line do Delphi ou análise o mapa de hierarquia de classes que vem com o produto.

Definindo suas próprias exceções

Adicionalmente ao recurso de manipulação de erros com as classes existentes, você poderá também,em condições específicas, usar o mesmo mecanismo usando classes de exceções definidas por vocêmesmo. Para isto, é necessário:

• Declarar um objeto de exceção;• Disparar a exceção.

Como exceções são objetos, definir um novo tipo de exceção é tão simples quanto declarar um novotipo de objeto. É sempre uma boa idéia derivar qualquer novo tipo de exceção a partir de Texceptionou uma das outras exceções padrão. Isto porque se você disparar sua exceção em um bloco de códigoque não está protegido por um manipulador de exceção específico para aquela exceção, o manipuladorpadrão será certamente chamado. Por exemplo, considere a declaração seguinte:

Type EmyException = class(TException);

Se você dispara EmyException mas não provê um manipulador específico para esta classe, ummanipulador para Exception (ou o manipulador padrão) ainda assim irá manipular a exceção. Isto podetambém ser compreendido com a seguinte explicação: se você cria sua exceção derivando-a deEIBInterbaseError (um manipulador mais específico para algumas exceções de acesso ao banco dedados Interbase), algumas exceções mais genéricas ou não relacionadas ao objeto ascendentes talveznão pudessem ser manipuladas corretamente.

Finalmente, você poderá também usar blocos de proteção conjugados, para prover a segurança emalgumas situações mais complexas. Veja o exemplo abaixo:

Try

Page 89: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

89

//bloco protegido Try

Except //manipulador de exceção local End;

Except //manipulador de exceção globalEnd;

O uso de exceções é um dos mecanismos mais poderosos para tornar a sua aplicação segura e robusta.Ao mesmo tempo, seu uso e extensão é uma tarefa simples e de fácil entendimento.

Guardando informações na Registry e em arquivos .ini

A Registry é um banco de dados hierárquico usado para armazenamento de configurações einformações gerais de aplicativos. O conhecimento da estrutura da Registry é importante paraprogramadores de qualquer tipo, pois certamente seus aplicativos precisarão guardar as mais variadasconfigurações. Como a Registry é um recurso exclusivo da plataforma Windows, não há suporte a elanos objetos da biblioteca CLX (multiplataforma). A VCL, contudo, oferece um vasto suporte para otrabalho com este banco de dados.Finalmente, você precisa considerar que nem sempre poderá gravar ou ler dados na Registry. Nossistemas Windows Server (como Windows NT e 2000), um determinado usuário ou grupo de usuáriospode não possuir tal direito. Isto significa que, se um usuário autenticado que não possui tais direitostentar acessar um programa que usa a Registry para guardar informações, possivelmente esteprograma não se comportará de modo adequado ou mesmo não funcionará.

A classe TRegistry

A classe Tregistry provê inúmeros métodos que permitem acessos de leitura/escrita na Registry comgrande facilidade. Os programadores certamente devem se inteirar dos padrões adotados pelaMicrosoft para o trabalho com esta ferramenta, que podem ser resumidos em:

• Uso hierárquico de dados e informações;• Destinação específica das raízes principais da Registry;• Tipos de dados aceitos.

Existem atualmente as seguintes raízes na Registry:

• HKEY_CLASSES_ROOT• HKEY_CURRENT_USER• HKEY_LOCAL_MACHINE• HKEY_USERS• HKEY_CURRENT_CONFIG• HKEY_DYN_DATA

Page 90: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

90

Na maioria das situações você deve as chaves “HKEY_LOCAL_MACHINE/Software/Minha Empresa/MeuPrograma” para gravar dados específicos de sua aplicação.

Tregistry precisa de trbalhar em um root, que é uma das raízes acima descrita. O root padrão, casovocê não especifique outro, é HKEY_CURRENT_USER.Também pode ler, criar ou alterar qualquer chaveou dados nesta estrutura através dos seguintes métodos:

CreateKey – Cria uma nova chave no caminho especificado, com em

Reg.CreateKey(‘software\Borland\Delphi\Dados’);

OpenKey – Abre uma chave. Se ela não existir, pode criá-la. Observe:

Reg.OpenKey(‘software\Borland\Delphi\Dados’);

Isto irá criá-la se não existir, mas

Reg.OpenKey(‘software\Borland\Delphi\Dados’, false);

Impede a sua criação.

CloseKey – Fecha uma chave

DeleteKey – Deleta uma chave com todos os seus valores, veja:

Reg.DeleteKey(‘nome da chave a deletar. Cuidado!!!’);

KeyExists – Retorna um valor boolean que diz se a chave existe ou não. A pesquisa é feita nas chavesabaixo da atualmente aberta.

If not Reg.KeyExists(‘Dados’) then Reg.CreateKey(‘Dados’);

ValueExists( ) – Verifica se um determinado valor existe dentro da chaveReadString( ) – Retorna o conteúdo de um valor de texto em uma chave.ReadInteger( ) – Retorna o conteúdo de um valor inteiro em uma chave.ReadBool( ) – Retorna o conteúdo de um valor boolean em uma chave.ReadFloat( ) – Retorna o conteúdo de um valor de número decima em uma chave.

É possível também escrever um valor em uma chave com métodos similares aos de leitura.

WriteString ( )WriteInteger ( )WriteBool ( )WriteFloat ( )

Na verdade, existem métodos para leitura e escrita de dados em muitos outros formatos como binário,data, DateTime, currency etc. Para uma referência completa, consulte a ajuda on-line do Delphi.Veja um exemplo completo de um procedimento que salva configurações de um aplicativo e outro queos lê:

Procedure Tform1.LerConfiguracoes;

VarReg := Tregistry;

Page 91: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

91

Begin

Reg := Tregistry.Create;Reg.RootKey := HKEY_LOCAL_MACHINE;Reg.OpenKey(‘software\Cooperi\Notepad\Dados’);Form1.Height := Reg.ReadInteger(‘Altura’); //Altera a altura do formulárioForm1.Width := Reg.ReadInteger(‘Largura’); //Altera a largura doformulárioForm1.Caption := Reg.ReadString(‘Titulo’); //Altera o caption da janelaForm1

Reg.CloseKey;Reg.Free;

End;

Agora, o procedimento que escreve os valores escolhidos pelo usuário, depois de redimensionar oformulário e alterar caption do mesmo através de um TEdit:

Procedure TForm1.GravaConfiguracoes;varReg := Tregistry;

BeginReg := Tregistry.Create;Reg.RootKey := HKEY_LOCAL_MACHINE;Reg.OpenKey(‘software\Cooperi\Notepad\Dados’);Reg.WriteInteger(‘Altura’,Form1.Height);//Grava a altura do formulárioReg.WriteInteger(‘Largura’,Form1.Width);//Grava a altura do formulárioReg.WriteSTring(‘Titulo’, Edit1.Text); // Grava o caption da janela Form1

Reg.CloseKey;Reg.Free;end;

A classe TIniFile

Esta classe está presente por compatibilidade com os sistemas Windows 3.x, que grava informações earquivos de inicialização (.ini). Desde o advento da Registry, este método de gravar informações temsido abandonado, uma vez que a Registry oferece infinitamente mais recursos do que simples arquivostexto de inicialização. Não use esta classe, a não ser que você tenha boas razões para fazer isto.Como a classe TiniFile está baseada na leitura e escrita de strings em arquivos texto, você não poderásalvar diversos tipos de dados em arquivos deste tipo. Ainda que seja possível guardar representaçõesde binários em arquivos texto, existem dados mais complexos que certamente lhe trarãoaborrecimentos se insistir no uso de arquivos de inicialização.Os arquivos de inicialização estão divididos em seções, dentro das quais encontram-se os valores. Useos métodos:

ReadSection – Coloca nomes das chaves em um TStringsReadSections – Coloca todas as seções em um TSTringsReadSectionValues – Coloca os valores de uma determinada chave em um TSTringsReadString – Retorna a string de um valor de um valor em uma seçãoWriteString – Escreve uma string em um valor de uma seção

Page 92: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

92

Existem ainda outros métodos relacionados à classe TiniFile. Consulde a ajuda do Delphi para umareferência completa.

Nota: Ao contrário das classes que lidam com a Registry, a classe TiniFile está disponível na CLX.

A seguir veja um exemplo de utilização de TregIniFile:

procedure TForm1.FormActivate(Sender: TObject);

var MyIniFile: TIniFile;begin MyIniFile := TIniFile.Create('myapp.ini'); with MyIniFile do begin if ReadBool('AutoLoad', 'FormProperties', False) = True then begin Visible := ReadBool('FormOptions', 'Visible', True); Color := TColor(ReadInteger('FormOptions', 'Color', clWindow)); Caption := ReadString('FormOptions', 'Caption', 'Main'); end; MyIniFile.Free;end;

A classe TRegistryIniFile

TregistryIniFile tem propriedades e métodos similares a TiniFile, mas lê e escreve na Registry doWindows. Usando uma variável do tipo TcustomIniFile (o ancestral comum de TiniFile, TmemIniFile eTregIniFile), você pode escrever um código genérico que acessa a Registry ou um arquivo deinicialização, dependendo de onde ele é chamado.

TRegistryIniFile apresenta um interface simples para acessar a Registry e dispensa anecessidade deconhecer a estrutura da Registry, pois TRegistryIniFile possibilita a manipulação da registry como se elafosse um arquivo de inicialização.

Estudando o objeto TForm

Todo o suporte oferecido pelo Delphi (através da VCL ou CLX) para aplicações gráficas está baseado naclasse Tform e seus descendentes. Esta seção irá explicar como funciona um formulário (Tform) ecomo um programador Windows e Linux pode trabalhar na construção de aplicações gráficasrequintadas.

Janelas e formulários no Win32

Um formulário é o fundamento mais importante para a construção de aplicativos gráficos. Umformulário é também uma “janela” de um programa, embora muitas vezes possa estar oculto. ODelphi implementa o suporte a formulários de desenho através do objeto TForm. Abaixo, você pode verum Tform vazio em tempo de desenvolvimento:

Page 93: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

93

Em um formulário você coloca controles que vão constituir a aparência de seu aplicativo para o usário,a fim de que ele possa interagir com o programa através do teclado, mouse ou outro periférico. Umformulário é um container, quer dizer um objeto que possui outros objetos dentro dele, como umbotão, uma caixa de edição ou uma imagem. Componentes não-visuais também podem estar contidosem um formulário. Ainda que não possam ser vistos pelo usuário, eles estão instanciado em um handle“pai”, que é o formulário.Devido ao fato de serem controles especiais, novos formulários não são inseridos através da palheta decomponentes, mas sim através da barra de ferramentas do Delphi.Uma aplicação usualmente contém múltiplos formulários: a formulário principal, que é aquele queforma a interface com o usuário mais importante, e outros formulários como caixas de diálogo, janelassecundárias e assim por diante. Você pode começar o seu formulário a partir dos inúmeros modelos existente do Object Repository, e também pode salvar um de seus formulários como modelo nestamesma ferramenta.

Métodos de acesso e destruição

Por padrão, o Delphi cria automaticamente o formulário principal de uma aplicação na memória.Contudo, é muito comum que a criação de outros formulários seja feita de maneira explícita peloprogramador, como através do seguinte fragmento de código:

Application.CreateForm(TForm1, Form1);

Criamos com isto uma variável global com o mesmo nome do formulário. Assim, todo formulário emuma aplicação tem uma variável global a ele associada. Esta variável é um ponteiro (pointer) para umainstância da classe do formulário, e é usada para referenciar o formulário durante a execução doaplicativo. Qualquer unidade que inclua a unidade do formulário em sua cláusula uses pode acessar oformulário via esta variável.Existem muitas outras maneiras de você escrer um código que funcione exatamente como omencionado acima, como por exemplo:

Form1 := Tform1.Create(self)

Figura X: um formulário Delphi emtempo de projeto.

Page 94: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

94

ou

Form1 := Tform1.Create(Application);

No primeiro exemplo, você cria a variável Form1, dizendo que será um ponteiro para a classe TForm1(que talvez descenda de TForm), e chama o método create da própria classe TForm1.No segundo caso, ocorre o mesmo, mas você chama o método Create de TApplication). A variávelglobal Application está presente em todos os aplicativos Delphi e a qualquer ponto do seu código-fonte.O método Create, contudo, apenas cria uma intância de TForm1 na memória, mas não o exibe para ousuário. Para você “mostrar” um formulário na tela, é necessário chamar o método Show ouShowModal.

• O método ShowModal exibe o formulário de maneira “modal”, quer dizer, exclusiva. Você precisaráfechar o formulário aberto por ShowModal para poder acessar qualquer outra janela de seuaplicativo. Uma janela de Login de usuário é um exemplo típico de chamada a este método.

• O método Show exibirá a janela de maneira normal, sem impedir o foco em outra.

Você pode criar várias instâncias de Tform1 em seu programa, o que significa que terá várias “cópias”da mesma janela na tela. Embora existam diversas situações onde este comportamente é desejável, emmuitos casos preferiríamos evitar novas cópias de Tform1. Você pode fazer isto de forma muitosimples, usando a função Assigned para verificar se já existe alguma cópia de Tform1 em uso. Veja oexemplo abaixo:

procedure Tform1.Butao1Click(Sender: Tobject)begin if not Assigned(Form2) then //testa se form2 não está na memória Form2 := Tform2.Create(self); //se não estiver cria uma instância Form2.Show;//exibe formsEnd;

Existem muitas formas de destruir um formulário na memória. Esta atenção, aliás, é de grandeimportância. Lembre-se sempre : o que não precisar manter em memória, deve ser liberado!

Uma maneira muito comum é através do método Free. Este método liberará a instância de TFomr2 namemória. També existe uma bordagem muito recomendada, que consiste na utilização do manipuladorde eventos OnClose da classe TForm. Este manipulador sempre será chamado quando a janela formfechada por uma ação explícita do usuário ou programaticamente. Veja um exemplo:

procedure TForm2.OnClose(Sender: Tobject; var Action: TCloseAction)begin Action := caFree; //destrói Form2 da memória Form2 := nil; //anula o ponteiro da instânciaend;

Em outro exemplo de aplicativo “chato” que sempre reconfirma se o aplicativo deve ser encerrado:

procedure TForm1.OnClose(Sender: Tobject; var Action: TCloseAction)begin //obs: Form1 é o formulario principal da aplicação

Page 95: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

95

if MessageDlg('Deseja realmente fechar a aplicação?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then Action := caFreeelse Action := caNone;end;

Tipos de formulários

O Windows suporta muitos tipos diferentes de formulários, que possuem finalidade e aparênciadiversas. A classe Tform oferece suporte a todos os tipos, entre eles os mais novos estilos lançados como Windows XP.Entre os estilos destacamos:

• Formulários normais (são o tipo mais comum);• Formulários MDI (dão suporte à introdução de interfaces MDI, como as dos aplicativos do MSOffice;• MDI Child (formulários “filhos” de um formulário MDI);• StayOnTop (formulários sempre visíveis).

Além disto temos:

bsdialog (janela não redimensionável, comum para caixas de diálogobsSingle (janelas não redimensionável, com bordas simples)bsNone (janela não redimensionável e sem borda);bsSizeable (janela redimensionável e com bordas)bsToolWindow (janela não redimensionável com borda simples e barra de título pequena)bsSizeToolWin (janela redimensionável, com bordas e barra de título pequena)

O objeto TFrame

Um frame (TFrame), tal como um formulário (TForm), é um container para outros componentes. Umframe usa os mesmos mecanismos gerais de instanciação e destruição de componentes que estão nelecontido, assim como as mesmas relações de ligação e dependência de propriedades (parent) com eles.Em alguns casos, contudo, um frame se parece mais como um componente customizado que é inseridono formulário. Os frames podem ser salvos e colocados na palheta de componentes para fácilreutilização. Após um frame ser criado e salvo, continua a funcionar como uma unidade e a herdar asmudanças feita nos componentes nele contidos, inclusive outros frames. Ou seja, quando um frame éinserido em um formulário ou em outro frame, conntinua a herdar as mudançãs feitas no frame doqual deriva.O uso de frames (tal como a arquitetura orientada a objetos) é um dos grandes fatores de

Figura X

O Frame“localizar” emtempo de projeto.

Page 96: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

96

reaproveitamento de código em aplicações Delphi. Você pode criar um frame que contenha rotinas eobjetos que você sabe que irá precisar ao longo de mutos formulários em uma aplicação ou entrevários projetos diferentes. Como exemplo, imagine que você desenvolveu um frame destinado aencontrar ocorrências de palavras em um editor de texto, que é completamente funcional e encerradoem si mesmo. Todo o código necessário para fazer esta operação já está presente no próprio frame.Então você poderá usar instâncias deste frame em quantas aplicações desejar ou em qualquer janelade uma aplicação sem inserir nem uma linha de código sequer. Mais do que isto. Se alterar o frameoriginal, por exemplo dotando- de novos recursos, todas as aplicação passam automáticamente asuportar o novo recurso. Esta características tornam um frame um formulário muito parecido com umcomponente qualquer.Quando conheçer o poder dos frames nunca mais deixará de usá-los em suas aplicações, e pouparáhoras de programação.

Construindo a interface com o usuário

Uma interface gráfica é mais fácil de usar quando controles e informações relacionadas sãoapresentadas em grupos. Existem muitos controles que são extremamente comuns no ambienteWindows, com os quais os usuários de seu aplicativo estão certamente acostumados. Entre elesincluimos Painéis, barras de ferramentas, menus, barras de status e outros. Este tópico procuraintroduzir as técnicas mais comuns de programação e desenho de interfaces de aplicativos usandoDelphi.

Action Lists

Action Lists (listas de ações) permitem a você centralizar a resposta para os comandos do usuário(ações) em objetos tais como menus e botões. Uma definição mais técnica diria que Actions sãocomandos do usuário que operam em objetos alvo. Você cria ações no Action List Component Editor, eas conecta a controles via seus links (a propriedade Action). A seguir são descritos os diversoselemintos usados em um mecanismo envolvendo action / action List.

• Um action (TAction) é a implementação de uma ação, tal como copiar um stexto selecionado emum objeto alvo, por exemplo um controle de edição de texto. Uma ação é disparada em resposta aum comando do usuário, um click do mouse em um controle em um formulário, por exemplo.Existem muitas classes derivadas de TAction que implementam ações específicas, comocopiar/colar/recortar, abrir um documento, chamar o sistema de ajuda, alinhar o parágrafo de umtexto e muitas outras ações de forma completamente automática.

• Uma lista de ações (TactionList) é um componente que mantém uma lista de ações (TAction).Listas de ações são usadas em tempo de projeto para trabalhar com a interface de seu programa.

• Um vínculo de ação (TactionLink) é um objeto que mantéma conexão entre as ações e os controles.

• Um cliente de uma ação é tipicamente um ítem de menu ou um botão como Tbutton, TtoolButton,TspeedButton, TcheckBox etc. Uma ácão é instanciada por um correspondente comando no cliente;em muitos casos um click no cliente é associado com o método Execute de uma ação.

• Um alvo de uma ação é, com freqüência, um controle, tal como um TrichEdit, um Tmemo ou umcontrole de banco de dados.

Page 97: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

97

Você pode adicionar uma lista de ações (TactionList) em seu formulário ou em qualquer tipo demódulo de dados e inserir ações (TAction) de forma coordenada e agrupada de acordo com afinalidade das ações. Veja abaixo uma lista de ações com vários objetos TAction muito usados emeditores de texto.

Centralizando código com listas de ações

Muitos controles têm uma propriedade publicada chamada Action. Quando você vincula um dessescontroles com um determinado TAction, este copia suas propriedades (tais como enabled, caption,ImageIndex e outras) para o controle vinculado. Na verdade, todas as propriedades em comum entre oTAction e o controle (exceto Name e Tag) são dinamicamente vinculadas a este. Desta forma, porexemplo, é possível centralizar o código em uma ação e um objeto e evitar a duplicação de código;quando você desabilita um TAction, ele faz o mesmo com todos os controles a ele vinculado. Isto éclassicamente necessário quando você tem um aplicativo com um menu principal, botões em barras deferramentas e menu local contendo as fornecendo funcionalidades.

Executando ações

Quando um controle vinculado a um TAction é “clicado”, o evento OnExecute ocorre para seu Tactionassociado. Por exemplo, o código abaixo ilustra um manipulador de evento OnExecute para um TActionque alterna a visibilidade de um barra de ferramentas (TtoolBar):

procedure TForm1.Action1Execute(Sender: TObject);begin{ alterna a visibilidade de Toolbar1}ToolBar1.Visible := not ToolBar1.Visible;end;

Figura X:Um ActionManagerexibindo diversars ações.

Page 98: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

98

Atualizando ações

Quando um aplicação encontra-se ociosa, o evento OnUpdate ocorre para todas as ações que estãovinculadas a um controle que está sendo exibido. Este mecanismo oferece a oportunidade para asaplicações execu’tarem de forma centralizada as operações de abilitação/desabilitação,marcação edesmarcação dos controles. Por exemplo, veja como é possível escrever um código que irámarcar/desmarcar um TAction (e seus controles) à medida em que uma barra de ferramentas estivervisível ou invisível:

procedure TForm1.Action1Update(Sender: TObject);begin{ Indica se ToolBar1 is visível agora }(Sender as TAction).Checked := ToolBar1.Visible;end;

Nota: Não escreva códigos extensivos no manipulador OnUpdate de um TAction. Devido ao fato deeste evento ser acionado quando a aplicação encontra-se ociosa, este evento será acionado muitasvezes e de forma repetida, comprometendo por inteiro o desempenho do aplicativo.

Ações pré-definidas

Existem muitos tipos de ações pré-definidos que são específicas para executar determinadas tarefas,como alterar a fonte/cor/tamanho de um texto, alinhar parágrafos, abrir/salvar arquivos, chamar osistema de ajuda, navegar e editar dados em um banco de dados e muitas outras.Como ações (TAction) são objetos, você pode criar ações que tenham um comportamento que atendaa uma necessidade específica, por exemplo manipular mídias em unidades de CD-ROM ou disparar umbrowser a partir de um TLabel vinculado ao seu novo TAction. Você pode criá-los como desejar e, umavez criados, estarão disponíveis para o reuso quando necessário.Para uma referência completa aos tipo pré-definidos existentes consulte a ajuda on-line do Delphi.

Desenvolvendo menus

Os menus provêem um amaneira fácil para organizar os recursos de sua aplicação em grupos lógicosde items. Os usuários Windows estão tão acostumados a trabalhar com este elemento nos aplicativos,que a inserção de um menu em um aplicativo certamente é um fator que pode auxiliá-los a encontraro que querem que seu aplicativo faça. Este tópico introduz o conhecimento de como desenvolvermenus em aplicativos Delphi, assim como explorar as novas capacidades de organização introduzidascom os menus no Windows 2000.

Page 99: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

99

O Menu Designer

Você desenha menus para sua aplicação usando o Menu Designer. Antes de poder iniciar o uso deMenu Designer, adiciona ao seu projeto um componente MainMenu (TmainMenu) ou um PopUpmenu(TpopUpMenu) no seu formulário, encontrados na página “Standard” da palheta de componentes. UmMainMenu cria um menu que é fixado logo abaixo da barra de título do formulário, enquanto umPopUpMenu é acionado com o botão direito do mouse sobre um controle ao qual está vinculado. Vocêdesenvolve um menu exatamente da mesma maneira que acessa-os em qualquer aplicativo, à exceçãode que em tempo de projeto é possível selecionar e manter foco em um item de menu em particular.Veja abaixo uma visão do desenvolvimento de um menu com o Menu Designer:

Usando esta ferramenta é possível selecionar cada um dos itens que compõem o seu menu e usar oObjetc Inspector para configurar suas propriedades etc. Um menu pode estender-se indefinidamentetanto no sentido vertical como no horizontal, ao criar-se novos itens abaixo de um “raíz” ou criarsubmenus a partir de um outro item. Como são recursos muito comuns em vários aplicativos, você nãodeve deixar de criar um menu completo em seu aplicativo, sempre quando parecer conveniente.A aparência de um menu pode ser modificada significativamente por diversos fatores:

• Uso de bitmaps junto de cada item;• Uso de menus com estilos diversificados;• Uso de efeitos ao acessá-los;• Desenhando-se em código a sua aparência (OwnerDraw).

O uso de bitmaps pode enriquecer bastante o seu menu, além de orientar o usuário em busca de umrecurso, tal como fazem os botões de barras de ferramentas. O Windows também tem enriquecidobastante a aparência de menus, através de menus complexos como o presente no Windows 2000 ougraficamente requintado como os menus do Windows XP.Apesar de todos estes recursos, você pode ainda desenhar o seu menu como bem entender escrevendocódigos que desenhem na superfície dos menus a aparência desejada.

Menus estilo Windows 2000 e XP

Figura XO menu designer doDelphi

Page 100: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

100

O Delphi 6 introduziu o suporte ao desenvolvimento de menus complexos e associados a umgerenciamento central de ações e barras de ferramentas que foram lançadas com o Windows 2000. Omecanismo consiste basicamente de um gerenciador centralizado de ações configurável em tempo deexecução que controla a disponibilidade de barras de ferramentas e botões de forma automática. Alémdisto, permite que os items mais usados de um menu estejam sempre visíveis, independentemente daordem em que foram inseridos originalmente pelos programados de um aplicativo.O suporte oferecido pelo Delphi baseia-se basicamente no s objetos TactionManager,TactionMainMenuBar, TactionToolBar e, lançado como um release, TXPActionToolbar.

• TactionManager é um objeto gerenciador da aparência geral do conjunto menus e barras deferramentas. Contém todas as ações definidas para o aplicativo e permite que o usuário customizequais objetos deseja ver, entre bandas e botões, e em qual ordem deseja que apareçam os botões.Ainda outros recursos relacionados a tamanho de ícones e exibição de texto nos botões estãodisponíveis através deste gerenciador.

• TactionMainMenuBar implementa um mecanismo de renderização das ações existentes como itemsde menu. Trabalha juntamente com TactionManager e possui uma enorme quantidade depropriedades para customizar sua aparência.

• TactionToolBar igualmente implementa um mecanismo de renderização das ações, trabnalhando-as como botões de barras de ferramenta. Oferece muitos recursos extras às tradicionais ToolBar’se uma aparência moderna.

• TXPActionToolBar age da mesmaforma que TactionToolBar, porém criando dinamicamente menuse barras de ferramentas no estilo Windows XP.

Outras barras de ferramentas

O Delphi também oferece barras de ferramentas “cool”, algumas com estilos importados dos mesmosobjetos da API do windows que desenham as barras de ferramentas do Internet Explorer.

• TtoolBar implementa uma barra de ferramentas moderna e muito comum nos aplicativos atuaiscomo o próprio Delphi e os do pacote MS Office 97. São barras de ferramentas flutuantes que setransformam em janelas quando arrastadas para fora de seu container (tipicamente umTcontrolBar).

• TcoolBar implemeta barra de ferramentas no estilo I. Explorer. Usa os mesmos mecanismos básicosde TtoolBar, porém oferece uma aparênciabem diferente

As imagens abaixo mostram um navegador WEB on-line que usa TCoolBar e um corte de umaTToolBar.

Figura XCorte da barra deferramentas do Delphi 6:um bom exemplo de uso deTToolBar

Page 101: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

101

Trabalhando com arquivos

Esta tópico descreve o fundamental do trabalho com arquivos em Delphi. Você conhecerá os tipos dearquivos comuns e aprenderá a manipular dados em disco, assim com as funções essenciais disponíveispara copiar, deletar ou mover um arquivo em seu disco.

Tipos de arquivos

O Delphi oferece suporte à criação e manipulação de qualquer tipo de arquivo que você desejar.Podemos categorizá-los de acordo com o tipo de dado que guardam. Entre os tipos de dados básicos,podemos citar: texto simples, binários. Arquivos texto contém apenas caracteres e são muito comunsnas mais diversas plataformas; arquivos binários guardam dados em formato binário codificado e sãocom freqüencia ilegíveis para os aplicativos que não sabem como lidar com eles, isso é “decodificá-los”.O Delphi ainda oferece suporte amplo a armazenamento de streams em arquivos.

Usando arquivos texto

Arquivos texto são aqueles que guardam caracteres comuns, sem estruturas de dados mais complexas.Você pode usar arquivos texto para muitas coisas, como guardar configurações, armazenar dados etc.A manipulação de arquivos texto usando o Object Pascal é extremamente simples. Existem muitosmétodos de diversos objetos que são capazes de fazer qualquer tarefa em um arquivo texto.

Figura XExemplo de uso de barras de ferramentas com TcoolBar em um navegador WEB construído com Delphi.

Page 102: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

102

Criando um editor de texto funcional

Como exemplo do uso de arquivos, iremos desenvolver agora uma aplicação que abre/gera arquivostextos. Adicionalmente, você poderá entrar em contato com alguns dos principais objetos comumenteusados na criação de aplicativos, como menus, botões, barras de ferramentas etc. Este aplicativofuncionará exatamente como o Notepad do Windows, porém as capacidades relacionadas a Automationpresentes no Notepad só serão implementadas quando estudarmos a tecnologia COM.

Controles de edição de texto

O Delphi oferece alguns controles para editar grande quantidade de texto. Resumem-se, basicamente,ao controle Tmemo (para edição de texto plano) e TrichEdit (para edição de texto formatado em RTF).Os dois controles têm capacidades e métodos semelhantes, exceto o fato de TrichEdit ser capaz deatribuir características de parágrafo e fonte ao documento, tais como alinhamento, cor e estilos defonte. Contudo, como uma das características mais marcantes da VCL e da CLX é a grande derivaçãode objetos com capacidades extendidades, você poderá encontrar muitos outros controles queextenderam bastante as características originais de Tmemo ou TrichEdit. Você poderá instalá-los e usá-los. Iremos construir um aplicativo simples para, paulatinamente, agregar recursos novos.

O projeto MemoEdit

MemoEdit é nome dado a este editor novo. Nós o construiremos usando os seguintes objetos:

• Menus• Barras de ferramentas• Barra de status• Um memo (Tmemo)

Inicie um novo projeto no Delphi e salve-o com o nome MemoEdit (ou outro que desejar, afinal),salvando a unidade com o nome Main. Neste momento só temos uma janela no nosso programa, que éa janela principal de MemoEdit. Posemos selecionar esta janela e alterar o seu nome para FrmMain.Pronto. O nosso editor está quase pronto. Não acredita? Pois então observe agora que todas asprincipais funcionalidades inerentes a um editor de texto, como abrir e salvar um documento,selecionar, copiar, recortar ou colar texto e ainda outras serão implantadas sem uma única linha decódigo nosso. Então vejamos.

Inserindo um ActionManager

Para testar que é novo, vamos utilizar o sistema de gerenciamento de menus e barras de ferramentaslançados com o Windows 2000. Não se preocupe, ele vai funcionar em todas plataformas Win32.Insira um TactionManager e um TImageList no nosso formulário. Como você sabe, TActionManagergerenciará todo um conjunto de ações, menus etc, enquanto TimageList será um receptáculo para asimagens compartilhadas entre menus e barras de ferramentas. Vincule o TIMageList aoTactionManager escolhendo a lista de imagens a partir da proprieda ImageList do ActionManager.Agora a “mágica”: dê um duplo click no ActionManager do seu formulário e, na janela que se abre,escolha o menu “New Standard Actions” que está lidado ao botão “New Action”. Escolha então todas as

Page 103: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

103

operações cabíveis ao nosso editor, como copiar/colar/selecionar/abrir documento etc. O resultado deveficar parecido com a imagem ao lado.

É óbvio que não há mágica alguma, apenas inserimos objetos derivados de TAction que sabem comofazer uma ação específica, como manipular dados no Clipboard do Windows. Isto significa que eles noslivraram de escrever toadas estas funcionalidades.

Desenhando as barras de ferramentas e menus

Agora vamos desenhas os menus e as barras de ferramentas de MemoEdit. Para implementar osmenus, não vamos usar o Menu Designer, pois nossos menus usam um mecanismo diferenciado deimplantação.Insira um objeto ActionMainMenuBar no formulário. Acesse o Object Inspector o ActionMainMenu aonosso ActionManager. Pronto, agora ele poderá criar clientes (items de menu) que se vinculam a açõesdo ActionManager. Façã isto assim:

1. Selecione o ActionManager e acione a sua propriedade ActionBars. Isto abrirá a janela de novositems do ActionManager

2. Crie um novo item escolhendo New;3. No Object Inspector, vincule a o nosso ActionMainMenu ao novo item criado através da

propriedade ActionBar do item criado.4. Para criar o menu “Arquivo” (topo do menu), selecione a propriedade “Items” da lista de barras

que você acabou de definir.5. Clique no botão “Add Item” e altere a propriedade “Caption” deste item criado para “&Arquivo”

Nota: O símbolo “&”, quando usado em menus, coloca um sunlinhado (underscore) debaixo da letraseguinte a ele, definindo assim um atalho de teclado para este menu.

Pelo mesmo processo cri os menus “&Editar” e “Aj&uda”. Agora é hora de criar os items derivados dasraízes de menu que acabamos de criar. O que podemos observar deste mecanismo é que cada item de

Figura X

O ActionList Editor exibindodiversas ações pré-definidas.

Page 104: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

104

menu em uma mesma lista será exibido no mesmo nível (horizontalmente), enquanto cada item possuisua própria propriedade “Items” que cria os menus inseridos abaixo dele (verticalmente).Finalmente, vincule cada item de menu, exceto os menus do topo (raíz), a uma ação através dapropriedade Action dos items. Isto fará todo o serviço para você, com alteração do caption e inserçãode imagens nos menus.

Nota: Nunca altere propriedades como enabled, ImageIndex ou caption de um menu ou botão debarra de status ligado a uma ação. Altere estes dados sempre na ação.

A criação de uma barra de ferramentas segue a mesma lógica da dos menus, porém desta vez vamosusar o controle TactionToolBar. Existem maneiras diferentes de se implementar uma barra comTactionToolBar. Observe o que vamos fazer.

1. Dê um duplo click no ActionManager e, na página “Toobars”, crie uma nova barra de ferramentas.Feche a janela do ActionManager.

2. Acesse a propriedade “ActionBands” do ActionManager e escolha a barra de ferramentas criadaacima.

3. Todo o processo que segue é idêntico ao da criação de menus.

Exibindo informações sobre as funcionalidades de MemoEditor

Par completar os recursos de MemoEditor ligados aos menus e barras de ferramentas, implantaremostambém uma barra de status para passar alguns tipos de informações ao usuário. Usaremos umcomponente TstatusBar para isto. Ela será posiciona na parte mais inferior do formulário principal eexibirá, basicamente, mensagens de ajuda quando o usuário acessar um botão ou menu. Estasmensagens são strings e conhecidas no Win32 como “hints” e são divididos e 2 partes: “ShortHint” e“LongHint”.

• ShortHint é a mensagem que aparece em uma caixa flutuante contendo uma explicação curta dafuncionalidade de um controle (tipicamente um botão de barras de ferramentas);

• LongHint é uma mensagem maior e mais descritiva que você pode exibir em outros controles,como uma barra de status.

ShortHint e LongHint são separados pelo caracter “|”. Por exemplo, imagine que você definiu oseguinte hint para uma ação:

‘Salvar|Salva as alterações feitas no documento atual’

Temos então:

ShortHint = ‘Salvar’;LongHint = ‘Salva as alterações feitas no documento atual’

Isso é muito simples. Então insira um TstatusBar no formulário principal de nossa aplicação e altere oseu nome simplesmente para “Status”. Através da propriedade “Panels” crie 3 painés na barra destatus e redefina suas dimensões para que a exibição do hint não seja “cortada”. Os hints exibidos noscontroles vêm na verdade das ações a eles vinculadas. Precisamos prover agora uma mecanismo paraque os hints de cada ação sejam exibidos na barra de status.Tudo o que precisamos fazer é usar as capacidades do objeto Tapplication. Como já dissemos, todoaplicativo cria automaticamente uma instância global de um objeto Tapplication, que guarda muitasdas características de uma aplicação. Tapplication pode ser acessado a partir de qualquer ponto de seucódigo e possui um evento denominado OnHint, que é disparado todas as vezes que qualquer instância

Page 105: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

105

de qualquer objeto de um aplicativo vai exibir seu hint. Se é assim está fácil, basta usarmos um poucode polimorfismo atribuindo este evento OnHint a um procedimento que copiará o texto do hint para abarra de status. Nós criamos este procedimento, chamado ShowHint. Veja a declaração abaixo:

procedure TFrmMain.ShowHint(sender: TObject);beginStatus.Panels.Items[0].Text := Application.Hint;end;

Este procedimento simples copia o hint para o primeiro painel da barra de status, onde se mandouassociar o evento OnHint de Tapplication ao procedimento ShowHint ? Isto é definido durante a criaçãodo formulário.

procedure TFrmMain.FormCreate(Sender: TObject);beginApplication.OnHint := ShowHint;end;

Se você executar MemoEditor agora, logicamente só poderá ver o LongHint na barra de status, pois oWindows já sabe que os ShortHint’s devem ser exibidos nas janelas flutuantes e a implementação deOnHint para Tapplication resolve esta necessidade.

Editando textos

Agora vamos para o controle principal de nosso editor que é um tradicional TMemo. Insira um memono formulário principal e altere a sua propriedade Align para AlClient, a fim de que ocupe toda a áreadisponível do formulário. Retire o texto que se encontra na propriedade Lines do memo.Uma coisa é importante saber desde já. O controle memo apenas oferece um interface visual para aedição de dados (strings) que são armazenados na propriedade Lines, que é um Tstrings. Ou seja,quem possui a capacidade de armazenar/salvar/carregar o texto se dá através de um TSTrings(propriedade Lines). Mas o memo oferece muitos outros de edição visual não presente em um simplesTstrings. Pense na seguinte analogia: se desejamos nos refrescar com água em um dia de muito calor,certamente é a água que nos proporcionará um alívio. Mas podemos lidar com água em uma piscinaou em uma torneira do banheiro. Uma piscina é um ótimo invólocro onde a experiência com a água émuito mais interessante.Já que as ações pré-definidas já resolveram automaticamente inúmeros aspectos relacionados à ediçãodo texto em um memo, podemos pensar agora em 3 tarefas fundamentais a serem implementadas:

• Abrir documentos de arquivos;• Criar novos documentos;• Salvar alterações em arquivos.

Para nossa satisfação todas elas são de implementação fácil. MemoEditor só permite a edição de umdocumento por vez. Para criar novos documentos ou abrir um arquivo do disco, precisamos antes saberse o documento atual está modificado, pois, se não fizermos isto as modificações não salvas dodocumento atual serão perdidas. A classe Tmemo possui uma propriedade publicada denominada“Modified” que é um boolean que indica justamente se o documento foi alterado, mas ainda não salvo.Ficou fácil. Consultaremos modified todas as vez que o usuário tentar gerar um documento novo ouabrir um arquivo existente para advertí-lo sobre dados ainda não salvos. Como o responsável por abrira janela para escolha do arquivo a abrir é uma ação pré-definida do tipo TFileOpen, é certamente aí

Page 106: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

106

que encontraremos a solução, precisamente na criação de um manipulador de evento OnAccept daação (no exemplo a ação leva o nome “FileOpen1”.

procedure TFrmMain.FileOpen1Accept(Sender: TObject);beginif Memo.Modified then if MessageDlg('Existem dados ainda não salvos no documento atual. ' + 'Deseja ainda assim abrir outro documento?',mtConfirmation, [mbYes,mbNo],0) = mrNo then Abort;

Memo.Lines.LoadFromFile(FileOpen1.Dialog.FileName);

{a linha acima nunca é executada se o usuário apertar o botão “Não” na caixa de mensagem}end;

MessageDlg é uma função definida na unidade “Dialogs” que exibe uma caixa de diálogo do tipo“confirmação” com 2 botões (sim e não). Se o usuário disser “não” a operação será abortada pelaprocedure “Abort”; do contrário o texto do arquivo será aberto pelo método “LoadFromFile” do memo.

Isto faz a correta constrição no caso de tentar-se abrir um novo documento. Agora teremos de fazercoisa semelhante quando o usuário tentar criar um documento novo. A primeira coisa que nos vem àmente nestes casos é reaproveitar o código já escrito . Por que deveríamos repetir código aqui e ali,mesmo se usármos a velha técnica de copiar / colar? Um grande recurso que as linguagens orientadasa objetos possuem é justamente o polimorfismo, que permite a um objeto compartilhar ou comportar-se como outros dos quais descende direta ou indiretamente. E vamos fazer isto agora com poucasmudanças no código acima.A idéia básica é que o TAction (ActNew) que executa a operação de gerar um novo documento use omesmo código acima. Porém, como agora não vamos carregar um arquivo, mas simplesmente iniciarum novo documento, é preciso fazer uma pequena alteração no código acima, para que o manipuladorsaiba o que vai fazer de acordo com que objeto o chamar. Veja o novo código:

procedure TFrmMain.FileOpen1Accept(Sender: TObject);beginif Memo.Modified then if MessageDlg('Existem dados ainda não salvos no documento atual. ' + 'Deseja continuar ainda assim?',mtConfirmation, [mbYes,mbNo],0) = mrNo then Abort;

//agora, identifica a ação que disparou o manipuladorif Sender = FileOpen1 then Memo.Lines.LoadFromFile(FileOpen1.Dialog.FileName)else Memo.Lines.Clear;

end;

Só modificamos o final do código para identicar qual objeto que disparou (Sender) o manipulador.Também alteramos ligeiramente o texto da mensagem. Agora é só selecionar a ação ActNew e, noObjetc Inspector, vincular o evento OnAccept de FileOpen1 ao evento OnExecute de ActNew. Veja umcorte do Objetc Inspector com os eventos vinculados.

Page 107: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

107

Salvando os dados em arquivo

Salvar os dados de nosso memo em um arquivo a princípio é muito simples. Como a classe Tstrings jápossui métodos para isto, os desenvolvedores que criaram Tmemo unicamente encapsularam o métodoSaveToFile de Tstrings para Tmemo. Porém a situação se torna mais complexa quando percebemosque precisamos guardar o nome do arquivo atual para evitar de sempre chamar a tela “Salvar Como”toda vez que o usuário desejar atualizar os dados inseridos em um arquivo ou que abrir um arquivo eeditá-lo. Além disto, vamos colocar o nome do arquivo atual na barra de título da aplicação.

Como precisamos salvar o nome do arquivo (inclusive o caminho) em algum lugar, uma estratégiasimples é declarar uma variável privada global do tipo string em nossa unidade. Ela pode se chamar“FileName”. Sempre que o valor desta variável for vazio (‘’), podemos entender que não existe umdocumento selecionado atualmente ou que o usuário gerou um novo mas ainda não o salvou. Se umarquivo é aberto ou um novo é salvo pela primeira vez, a variável “FileName” conterá o seu nome.Desta forma, poderemos chamar o método SaveToFile sem Ter que abrir a caixa de diálogo para ousuário escolher um nome e local para o arquivo. Uma vez comprendida a estratégia adotada, observe-se que o usuário pode a qualquer momento salvar o arquivo com outro nome, tornando-o o arquivoatual.A classe TfileSaveAs, como se nome indica, sempre chama uma caixa de diálogo para salavar umarquivo. Ela foi desenhada para atender situações tais como as disponíveis no nosso menu “SalvarComo”. Teremos então de criar uma nova ação (TAction) personalizada. Dê a ela um nome tal comoActSave. O manipulador OnExecute de ActSave testará o contúdo da variável FileName, salvando osdados no arquivo do endereço exitente em FileName ou, caso FileName esteja vazia, chamará ométodo Execute de FileSaveAs. Veja como ficou escrito:

procedure TFrmMain.ActSaveExecute(Sender: TObject);beginif Filename <> '' then Memo.Lines.SaveToFile(FileName)else FIleSaveAs1.Execute;end;

Uma alteração nestes manipuladores ainda precisa ser feita. Teremos agora de escrever na variávelFileName sempre que um arquivo for aberto ou que um arquivo for salvo pela primeira vez (criado).Também teremos que “limpar” o conteúdo de FileName quando um usuário gerar um documento novonão salvo. Por fim, a função ExtractFileName (declarada na unidade SysUtils) irá escrever o nome doarquivo na barra de título. Para isto alteramos os manipuladores OnAccept de FileOpen1 e FileSaveAs1.Veja abaixo como o código final ficou:

procedure TFrmMain.FileOpen1Accept(Sender: TObject);

Page 108: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

108

beginif Memo.Modified then if MessageDlg('Existem dados ainda não salvos no documento atual. Desejaainda ' + 'assim abrir outro documento?',mtConfirmation,[mbYes,mbNo],0) = mrNo then Abort;

if Sender = FileOpen1 then begin Memo.Lines.LoadFromFile(FileOpen1.Dialog.FileName); FileName := FileOpen1.Dialog.FileName; Caption := 'MemoEditor - ' + ExtractFileName(FileName); end else begin Memo.Lines.Clear; FileName := ''; end;end;

procedure TFrmMain.FileSaveAs1Accept(Sender: TObject);beginMemo.Lines.SaveToFile(FileSaveAs1.Dialog.FileName);FileName := FileSaveAs1.Dialog.FileName;Caption := 'MemoEditor - ' + ExtractFileName(FileName);end;

Inserindo uma tela de créditos (“About”)

Iremos acrescentar também uma nova ação personalizada que irá chamar uma tela “About” deMemoEdit que nós criaremos. Para implementar esta funcionalidade vamos criar um novo formulárioem nosso aplicativo e salvar a unidade ce o formulário com os nomes “About” “FrmAbout”,respectivamente. No formulário novo faça as seguintes alterações:

1. Altere a propriedade caption para “Sobre MemoEdit”;2. Altere a propriedade Position para poScreenCenter para que o formulário aparece no centro da

tela;3. Altere a propriedade BorderStyle para bsDialog para definir o formulário como um caixa de

diálogo.4. Reduza o tamanho do formulário;5. Acesse os menus Projetc | Options e retire o formulário da lista “Auto – created forms”

Esta última ação irá impedir que nossa tela “About” seja criada quando a aplicação for executa, poisapenas desejamos criá-la quando o usuário fizer uma escolha explícita.

Na tela “About” insira um component Timage, um Tlabel e um TButton. A finalidade de cada um delesé exibir o ícone da aplicação, seu nome e fornecer um botão para o usuário fechar a tela “About”.Ajuste estes componentes na tela a fim de obter um desenho agradável. No Tbutton, altere apropriedade “ModalResult” para “mrOk’. Isto fará com que o botão se comporte como um confirmadorda caixa de diálogo, fechando-a automaticamente.

Page 109: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

109

Inserindo o ícone da aplicação na tela “About”

O Timage que colocamos na tela “About” tem o objetivo de mostrar o ícone da aplicação. Preferiremosinserir o ícone no Timage de forma dinâmica; isto é, a rotina que mostrará o ícone será escrita emcódigo. Assim se você alterar o ícone desua aplicação a tela “About” sempre mostrará o ícone correto.O melhor lugar para isto é durante a criação da tela. Veja o manipulador de eventos OnCreate danossa tela de créditos:

procedure TFrmAbout.FormCreate(Sender: TObject);beginImage1.Picture.Icon.Assign(Application.Icon);end;

Este código “assinala”, quer dizer, “copia” o conteúdo de Application.Icon para o Timage. Agora, sóprecisamos escrever algum código para chamar esta janela. Isto, conforme previsto, será feito emOnExecute da ação que criamos antes. Veja o código:

procedure TFrmMain.ActAboutExecute(Sender: TObject);beginFrmAbout := TFrmABout.Create(self);FrmAbout.ShowModal;end;

Também vamos destruir a janela “About” quando ela for fechada. Na verdade, ela mesma vai sedestruir. O melhor local para fazer isto é no evento OnClose da nossa tela de créditos. Precisamosfazer:

1. Destruir a janela para liberar a memória2. Liberar o penteiro a ela associado na memória

Veja o código abaixo:

procedure TFrmAbout.FormClose(Sender: TObject; var Action: TCloseAction);beginAction := caFree;//caFre destrói a janelaFrmAbout := nil; //Anulando o ponteiro de FrmAboutend;

Por fim, vamos associar um atalho de teclado para a ação que chama a tela “About”. Selecione estaação e, no Objetc Inspector, digite F1 (ou o atalho que quiser) na propriedade “ShortCut” da ação.Teste esta implementação.

Com isto terminamos a primeira etapa do desenvolvimento deste editor. Mais a frente adicionaremosnovos recursos para torná-lo ainda mais funcional.

Segue abaixo a listagem completa de seu código-fonte:

Page 110: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

110

Listagem 10 – MemoEdit.dpr

program MemoEdit;

uses Forms, Main in 'Main.pas' {FrmMain}, About in 'About.pas' {FrmAbout};

{$R *.res}

begin Application.Initialize; Application.CreateForm(TFrmMain, FrmMain); Application.Run;end.

Page 111: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

111

Listagem 11 – Main.pas

unit Main;

interface

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,Forms, Dialogs, StdActns, ExtActns, ActnList, ImgList, ActnMan, ToolWin, ActnCtrls, ActnMenus, ComCtrls, StdCtrls;

type TFrmMain = class(TForm) ActionManager1: TActionManager; ImageList1: TImageList; EditCut1: TEditCut; EditCopy1: TEditCopy; EditPaste1: TEditPaste; EditSelectAll1: TEditSelectAll; EditUndo1: TEditUndo; EditDelete1: TEditDelete; FileSaveAs1: TFileSaveAs; FilePrintSetup1: TFilePrintSetup; FileRun1: TFileRun; FileExit1: TFileExit; SearchFind1: TSearchFind; SearchFindNext1: TSearchFindNext; SearchReplace1: TSearchReplace; SearchFindFirst1: TSearchFindFirst; ActionMainMenuBar1: TActionMainMenuBar; ActionToolBar1: TActionToolBar; FileOpen1: TFileOpen; ActAbout: TAction; Status: TStatusBar; Memo: TMemo; ActNew: TAction; ActSave: TAction; procedure FormCreate(Sender: TObject); procedure ActAboutExecute(Sender: TObject); procedure FileSaveAs1Accept(Sender: TObject); procedure FileOpen1Accept(Sender: TObject); procedure ActSaveExecute(Sender: TObject); private { Private declarations } FileName: string; procedure ShowHint(sender: TObject);

public { Public declarations } end;

var FrmMain: TFrmMain;

Page 112: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

112

Listagem 12 – Main.pas (continuação)

Listagem 13 – Main.pas (continuação)

implementation

uses About;

{$R *.dfm}

procedure TFrmMain.FormCreate(Sender: TObject);beginApplication.OnHint := ShowHint;end;

procedure TFrmMain.ShowHint(sender: TObject);beginStatus.Panels.Items[0].Text := Application.Hint;end;

procedure TFrmMain.ActAboutExecute(Sender: TObject);beginFrmAbout := TFrmABout.Create(self);FrmAbout.SHowModal;end;

procedure TFrmMain.FileSaveAs1Accept(Sender: TObject);beginMemo.Lines.SaveToFile(FileSaveAs1.Dialog.FileName);FileName := FileSaveAs1.Dialog.FileName;Caption := 'MemoEditor - ' + ExtractFileName(FileName);end;

procedure TFrmMain.FileOpen1Accept(Sender: TObject);beginif Memo.Modified then if MessageDlg('Existem dados ainda não salvos no documento atual. Desejaainda ' + 'assim abrir outro documento?',mtConfirmation,[mbYes,mbNo],0) = mrNo then Abort;

if Sender = FileOpen1 then begin Memo.Lines.LoadFromFile(FileOpen1.Dialog.FileName); FileName := FileOpen1.Dialog.FileName; Caption := 'MemoEditor - ' + ExtractFileName(FileName); end else begin Memo.Lines.Clear; FileName := ''; end;end;

Page 113: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

113

Listagem 14 – About.pas

procedure TFrmMain.ActSaveExecute(Sender: TObject);beginif Filename <> '' then Memo.Lines.SaveToFile(FileName)else FileSaveAs1.Execute;end;end.

unit About;

interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,Forms,Dialogs, StdCtrls, ExtCtrls;

type TFrmAbout = class(TForm) Image1: TImage; Label1: TLabel; Button1: TButton; procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } public { Public declarations } end;var FrmAbout: TFrmAbout;

implementation

{$R *.dfm}

procedure TFrmAbout.FormCreate(Sender: TObject);beginImage1.Picture.Icon.Assign(Application.Icon);end;

procedure TFrmAbout.FormClose(Sender: TObject; var Action: TCloseAction);beginAction := caFree;FrmAbout := nil;end;end.

Page 114: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

114

Trabalhando com imagens e desenhos

O trabalho com gráficos e desenhos no Win32 é grandemente facilitado pela presença de uma API eum conjunto de rotinas completo que é responsável por gerar “imagens” na tela de um computador,conhecida como GDI (Graphic Device Interface). De fato, se pensarmos que tudo o que vemos na telanão passa de uma grande quantidade de pixels “iluminados” que, em conjunto, formam um desenhoou interface compreensível a olhos humanos, podemos compreender que o trabalho com gráficos é umpouco semelhante a uma tela de pintura de um artista: existe uma superfície a ser “pintada” e o artistausa diversos instrumentos para realizar a sua criação, tais como pincéis de variados tipos.A GUI do Win32 oferece-nos não só uma “superfície” a ser “pintada” como intrumentos (“pincéis”) emétodos bem desenvolvidos para “criar” um desenho na tela de um computador. Aplicativosfortemente gráficos, como muitos jogos, fazem um uso intenso destas possibilidades oferecidas pelaGDI.O Delphi oferece um amplo suporte para o desenvolvimento de aplictivos que trabalham com desenhosou gráficos de todos os tipos. Os componentes gráficos da VCL encapsulam a GDI, tornando muito fáciladicionar recursos gráficos ao seu aplicativo. Esta seção explicará como você manipular os principaisobjetos destinados a trabalhos com gráficos, e também criará uma aplicação de desenho gráfico.

Usando TCanvas como uma superfície de desenho

Para desenhar gráficos em uma aplicação Delphi, você sempre usa uma superfície de desenhoencapsulada pelo objeto Tcanvas. Você não desenha diretamente sob um objeto qualquer, poisTcanvas é sempre uma propriedade de um objeto, além de ser também um objeto. Uma das maioresvantagens de Tcanvas é que ele manipula recursos efetivamente e oferece dispositivos de contextopara desenhar na tela, na impressora ou em bitmaps e vetoriais. Objetos canvas estão disponíveisapenas em tempo de execução, de forma que você executa todo o trabalho sobre eles através decódigo.

A maneira como imagens aparecem na sua aplicação depende do tipo de objeto em cuja superfícievocê desenha. Se você estiver desenhando diretamente sob um canvas de um controle, a imagem édisparada imediatamente. Contudo, se você desenhar sob uma imagem offscreen (em memória) talcomo um Tbitmap ou Tjpeg, a imagem não é exibida até que você copie a imagem para o canvas deum controle. Isto é, quando estiver desenhando bitmaps e assinanalando-os para um Timage, aimagem só é atualizada quando o controle tem a oportunidade de processar sua mensagem OnPaint.Quando você está trabalhando com gráficos, freqüentemente encontra as expressões “drawing”(desenho) e “painting” (pintura). No sistema gráfico do Windows, é necessário distinguir um de outro:

• Drawing é a criação, em código, de um um único e específico elemento gráfico, tal como umalinha ou um quadrado.

• Painting é a criação da inteira aparência de um objeto. Painting usualmente envolve drawing, istoé, em resposta a eventos OnPaint, um objeto geralmente desenha algum gráfico. Um componenteTedit, por exemplo, pinta-se ao desenhar um retângulo e então desenha algum texto em seuinterior. Um Tshape, por outro lado, pinta-se ao desenhar um gráfico simples.

Para efeito de compreensão, observe que quando você maximiza a janela de um programa, o Windowsgera mensagens WM_PAINT que a VCL “encapsula” através de eventos OnPaint. Mas, enquanto algunssistemas operacionais cuidam automaticamente de manipular o redesenho de janelas que estãoinvalidadas, o Windows não o faz, pois, para o Windows, qualquer coisa desenhada na tela épermanente. Quando, por exemplo, uma janela é obscurecida ao começa a ser arrastada, o formulárioou um controle devem repintar a área obscurecida quando a operação de arrasto estiver terminada.

Tipos de objetos gráficos

Page 115: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

115

A VCL provê os objetos gráficos indicados abaixo. Todos estes objetos têm métodos para desenhar sobum canvas.

Objeto DescriçãoTPicture Usado para armazenar qualquer imagem gráfica. Quando desejar adiciona formatos de arquivos gráficos

adicionais, use o método Register de Tpicture. Use este objeto para manipula arquivos gráficos arbitrários.TBitmap Um poderoso objeto gráfico usado para criar, manipular e armazenar arquivos gráficos em disco. Existem muitos

formatos de gráficos bitmaps.TClipboard Representa um container para qualquer texto/gráfico etc que for copiado, cortado ou colado a aprtir de

aplicações.TIcon Oferece suporte ao formato Windows .ico.TMetafile Contém um meta-arquivo que guarda as operações requeridas para contruir uma imagem, ao invés de conter os

pixels de um bitmap. Meta-arquivos são extremamente escaláveis sem perder detalhes de imagens e requeremmuito menos memória que bitmaps, particularmente para dispositivos de alta resolução, como impressoras.Contudo, meta-arquivos são tão rápidos quanto bitmaps no processo de pintura da imagem.

Cada um destes objetos possuem muitos métodos de desenho, pintura, atualização, salvamento emarquivo, carregamento de arquivo, desenho de figuras geométricas e de texto, conversão de formatosetc. Criaremos um aplicativo gráfico que ilustrará o uso de alguns destes métodos.

Conhecendo TImage

Timage é um controle gráfico destinado à exibição de imagens de todos os tipos. Timage éversátil osuficiente para suportar processos de desenho e pintura tão diversificados como os de uma imagembitmap ou o de um metafile do Windows. Quando você usa TImage, o processo de pintura eatualização da imagem nele contido é manipulado automaticamente pela VCL, de forma que TIMage écapaz de conter imagens persistentes. Você usará um objeto Timage todas as vezes que desejaracrscentar uma imagem em seu aplicativo (como em uma tela de abertura, por exemplo) ou quandoconstruir aplicativos que exibem imagens a partir de arquivos de imagens. Como TImage encapsula umobjeto Tpicture através da sua propriedade publicada “Picture”, ele poderá suportar a exibição emanipulação de imagens de todos os tipos suportados por Tpicture, assim como os tipos adicionais queforem inseridos no suporte de Tpicture.

Criando um aplicativo de desenho funcional

Para ilustrar todo o trabalho com Tcanvas e alguns componentes que encapsulam grande parte dassuas funcionalidades através de propriedades, vamos criar agora um aplicativo de desenho e trabalhocom imagens. Este aplicativo também mostrará algumas técnicas comuns na abordagem de interfacesMDI implementados a nível do sistema operacional Windows.

O projeto do aplicativo

Técnicas MDI de manipulação de documentos

Page 116: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

116

Implementando os recursos de manipulação de arquivos

Implementando recursos de trabalho com imagens

Implementando recursos de desenho

Informações de arquivos

Técnicas avançadas de trabalho com gráficos

O Delphi permite manipular objetos gráficos de uma maneira tão simples que, do ponto de vista doprogramador, é realmente relativamente simples desenvolver recursos avançados, como tratamento deimagens, conversões de tipos ou criação de formatos personalizados de arquivos gráficos. Você podeduvidar disto, pensando que, na verdade, estas são tarefas titânicas. Contudo, verá que é mais fácilimplementar técnicas avançadas do que realmente imaginava.

Como os objetos gráficos são, evidentemente, visuais, a melhor forma de agilizar o desenvolvimento deaplicativos graficamente complexos, como jogos ou multimídias, por exemplo, é utilizar componentesque já possuam características visuais bastante avançadas e adequadas ao seu projeto. E estescomponentes já existem em enorme quantidade. Além daqueles que são instalados com o Delphi,existem muitas coleções de componentes exclusivamente destinados ao desenvolvimento de jogos,screen savers e multimídias. Nestas coleções encontramos botões gráficos de qualquer aparência,labels com efeitos os mais variados, painéis de exibição de filmes, menus altamente gráficos,manipuladores de efeitos de transição e muitos outros componentes. Apenas a título de exemplo,citaremos a biblioteca “TMS Instrumentation Workshop“, com mais de 110 componentes destinados aodesenvolvimento de multimídias diversas, apresentações e aplicativos de precisão técnica.

Outra estratégia que pode simplesmente eliminar todo o seu esforço de desenvolvimento, é utilizarbibliotecas e unidades de código que possuem muitas funções e procedimentos destinados aotratamento de imagens e às mais diversas tarefas comuns em aplicativos de trabalho com gráficoscomplexos, como o Adobe PhotoShop, por exemplo. Estas unidades e bibliotecas existem também emgrande quantidade, e você vai ficar feliz ao encontrar uma rotina que implementa uma funcionalidadeà qual você teria de gastar muito mais tempo para implementar sozinho. Este tópico irá mostraralgumas técnicas de trabalho com imagens.

Espectros de cores

Alguns aplicativos precisam exibir uma gama muito complexa de cores

Page 117: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

117

Rotacionando imagens

Invertendo imagens

Page 118: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

118

PP AA RR TT EE II II

DD EE SS EE NN VV OO LL VV EE NN DD OO AA PP LL II CC AA ÇÇ ÕÕ EE SS DD EE BB AA NN CC OO DD EE DD AA DD OO SS

Page 119: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

119

CC AA PP ÍÍ TT UU LL OO 99 -- TT EE CC NN OO LL OO GG II AA SS DD EE AA CC EE SS SS OO AA FF OO NN TT EE SS DD EE DD AA DD OO SS

Aplicações de banco de dados permitem aos usuários interagir com informações que são armazenadasem bancos de dados. O Delphi provê um suporte muito amplo e extensível a tecnologias de bancos dedados, que se extende a simples arquivos texto até muito complexos sistemas de banco de dadosrelacionais com acesso remoto. Você também pode acessar um mesmo banco de dados através detecnologias de acesso diferentes como Acesso nativo, BDE, DBExpress, Client Dataset ou ADO, todasdisponíveis no ambiente Delphi. Caso ainda assim julgar necessário, poderá desenvolver uma novatecnologia de acesso a partir da base flexível de TDataset.Este capítulo tem a intenção de introduzir o conhecimento das arquiteturas e tecnologias de acesso adados providos pelo ambiente Delphi. Cada uma destas tecnologias será analisada com muito maisprofundidade nos capítulos seguintes.

Page 120: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

120

Tipos de bancos de dados e acessos

O suporte Delphi para acesso a bancos de dados é extremamente vasto. Você pode usar diferentestecnologias de acesso a dados e diferentes bancos de dados, sempre de uma maneira bastanteuniforme. Você deve diferenciar de imediato o mecanismo de acesso a dados com o tipo do banco dedados. O mecanismo consiste na tecnologia de software que você pode usar para acessar umdeterminado tipo de banco de dados. Existem mecanismos genéricos (que oferecem suporte a diversostipos de bancos de dados de uma forma semelhante, freqüentemente através de drivers ou tecnologiasemelhante) e mecanismos específicos, que acessam um tipo de banco de dados em particular,freqüentemente de maneira direta, dispensando drivers de conexão. Os seguintes mecanismos estãodisponíveis para o Delphi 6.0

• Os componentes existentes na página BDE da palheta de componentes oferecem suporte a acessoa diversos tipos de bancos de dados usando a tecnologia conhecida como Borland Database Engine(BDE).

• Os componentes existentes na página Interbase e Interbase Admin oferecem um conjunto decomponentes para acesso direto a bancos de dados Interbase ou Firebird.

• Os componentes da página DataAcess oferece suporte ao desenvolvimento de aplicações debancos de dados distribuídas através da tecnologia MIDAS.

• Os componentes da página ADO usam ActiveX Data Objets (ADO) para acessar bancos de dadosatravés de um driver OLEDB.

• Os componentes da página DBExpress oferece suporte a acesso a bancos de dados através datecnologia DBExpress, uma tecnologia multi-plataforma de acesso a dados.

Além destes componentes desenhados para acessar dados através de tecnologias específicas, vocêpode também desenvolver qualquer tecnologia de acesso a qualquer banco de dados usando a baseuniversal de acesso a dados oferecida pela classe TDataset. Com efeito, existem no mercado umaquantidade muito grande de bibliotecas de componentes que usam a base oferecida por Tdatset paradesenvolver métodos específicos de acesso a muitos bancos de dados. Como exemplo, citemos asbibliotecas IBO (Interbase Objects) e FIBPlus para acesso direto à API de bancos de dadosInterbase/Firebird; a biblioteca de componentes NCOCI8 que oferece acesso direto a bancos Oracleatravés de chamadas à sua API e ainda muitas outras.

Dependendo da sua versão do Delphi, a BDE e a DBExpress incluem drivers para acessar diferentestipos de bancos de dados. Enquanto quase todos os tipos de bancos de dados conhecem tabelas(tables) que contêm informações, alguns tipos de banco oferecem também:

• Mecanismos de segurança;• Transações;• Dicionários de dados;• Integridade referencial, procedimentos armazenados e gatilhos (triggers).

Tipos de bancos de dados

Existem diferentes tipos de bancos de dados no mercado. Usando Delphi, você provavelmente poderáconectar-se a qualquer um deles; mas, caso você esteja acessando um formato proprietário poucoconhecido, ainda assim poderá usar o Delphi usando uma das seguintes estratégias:

• Desenvolvendo descendentes de TDataset que saibam como acessar o seu banco;

Page 121: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

121

• Desenvolvendo drivers ODBC que saibam como acessar o seu banco. Então, será possível usarnormalmente os componentes de acesso a bancos via BDE ou ADO;

• Desenvolvendo drivers OLEDB que saibam acessar o seu banco. Desta forma, é possível usar oscomponentes que utilizem a tecnologia ADO.

• Desenvolvendo drivers DBExpress que saibam como acessar os dados de seu banco. Assim, asolução que utilize tecnologia DBExpress estará acessível.

A tecnologia BDE oferece acesso a diferentes bancos de dados como: arquivos texto; Paradox, Xbase;Dbase; FoxPro; Visual FoxPro; MSAcess; Informix; Oracle; Interbase; Firebird; Sybase; MS SQL Server;DB2; CSV e texto formatado. O acesso a qualquer um destes bancos pode ser via um driver BDE ouentão via ODBC.Usando ADO você pode acessar os mesmos bancos que acessaria usando BDE, porém fará isto atravésde um driver OLEDB.A DBExpress suporta atualmente os seguintes bancos: Interbase/Firebird, Oracle, Informix.

Tecnicamente falando, os bancos de dados são classificados em 2 tipos básicos:

Bancos de dados locais.

São bancos de dados que possuem uma arquitetura de acesso mono-usuário e residem em um discolocal ou em algum ponto de uma rede local de computadores. Freqüentemente, esses bancos sãodedicados a um único sistema, e usam mecanismos de travas de registro mais ou menos restritivosporém, em todo caso, inadequados para acessos simultâneos concorrentes. Por isto, tais bancos são àsvezes chamados de bancos “baseados em arquivos”.Os bancos de dados locais podem ser mais rápidos do que bancos remotos, pois com freqüênciaresidem no mesmo sistema que o aplicativo de manipulação dos dados. Possuem uma maior limitaçãono que diz respeito à quantidade de dados que podem armazenar e à complexidade do modelo dedados a ser implementado.

Servidores de bancos de dados remotos

Servidores de bancos remotos comumente residem em uma máquina na rede. Eles usam StructuredQuery Language (SQL) como mecanismo de acesso, criação e manutenção de dados e metadados e,por isso, são comumente chamados de servidores SQL. Estes Sistemas Gerenciadores de Bancos deDados Relacionais (SGBDR) são mecanismos muito mais complexos que o simples processo de inserçãoou edição de dados, e fazem uma grande quantidades de tarefas de manutenção e gerenciamentoatravés de um “motor” ou Servidor SQL que deve estar sempre ativo.SGBDR’s são desenhados para uma grande quantidade de acessos concorrentes sem qualquermecanismo de travas de dados, propiciando um verdadeiro e sofisticado sistema de acesso multi-usuários baseados em transações. Também podem armazenar uma quantidade indefinida de dados,que não necessitam obrigatoriamente residir em um único computador, mas podem estar distribuídosem diversos servidores.

Arquiteturas de aplicações de bancos de dados

Aplicações de banco de dados são construídas a partir de elementos da interface com o usuário,componentes que manipulam o banco de dados e componentes que representam dados contidos em

Page 122: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

122

tabelas do banco de dados (datasets). A arquitetura de aplicações de bancos de dados é determinadapela f orma como você “organiza” estas peças.

Ao isolar os componentes de acesso ao banco de dados em um módulo de dados (TDataModule), épossível desenvolver formulários que o acessam e providenciam uma interface bastantes consistente. Oisolamento também permite ao desenvolvedor criar padrões de arquiteturas e compartilhar módulos dedados entre diversas aplicações. Muitos aspectos da arquitetura de sua aplicação de banco de dadosdependem do tipo de banco que você está usando, o número de usuários que irão compartilhar asinformações do banco e os tipos de informações contidas em seu banco de dados.

Pensando em escalabilidade

Ao iniciar o desenvolvendo de uma aplicação de banco de dados, você deve pensar de imediato emcomo poderá criar aplicações que sejam altamente escaláveis. Um bom planejamento de escalabilidadepara sua aplicação pode proteger um seu investimento em desenvolvimento quando, por alguma razão,o abandono do modelo de arquitetura de seu aplicativo se tornar imperativo. Muitos fatores podemexigir este abando, como:

• Aumento do número de usuários acessando seu banco de dados ou aumento de acessos ao banco;• Aumento do número de aplicações acessando seu banco de dados;• Aumento da quantidade de informações armazenadas em seu banco de dados.• Necessidade de disponibilizar dados de seu banco para uma quantidade desconhecida de pessoas

(como através de páginas WEB, por exemplo).

Muitas técnicas de escalabilidade de aplicações estão à sua disposição, seja qual for a arquitetura quedesejar implementar, mas aplicações multi-camadas provêem o máximo de vantagens emescalabilidade.Os componentes de acesso a dados da VCL tornam fácil desenvolver aplicações escaláveis ao abstrairos recursos de um banco de dados e dos dados armazenados. Seja qual for a arquitetura escolhida,você pode isolar seus elementos da interface com o usuário de uma camada de acesso aos dados. Afigura seguinte ilustra esta estratégia:

O desenho de uma janela com título “UI” (user interface) reprsenta a interface com o usuário, ondesão exibidos os dados. No módulo de dados (“Data Module”) estão os componentes que acessam obanco de dados.

Se você isola desta forma um módulo de dados, torna-se fácil desenvolver outro módulo de dados querealizará tarefas específicas em outro banco, ou mesmo ler dados em bancos de outros tipos a fim detranaferí-los para o seu banco. Uma aplicação que acessa dados de um banco de dados sempredeveria possuir um módulo de dados.

Figura – Arquitetura genérica de acesso a dados via datasets.

Page 123: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

123

Aplicações de uma camada

Quando você desenvolver uma aplicação que usa informações que não serão compartilhadas entremuitos usuários, você pode desejar usar uma banco de dados local em uma arquitetura simples(single-tiered application). Este apanhado pode ter vantagens como alto desempenho (porque os dadossão armazenados localmente) e não demandar a compra de um servidor de dados robusto. Contudo,esta arquitetura possui limitações fortes quanto à quantidade de informações que o banco podearmazenar e o número de usuários que o banco pode suportar.Em aplicações de 1 camada, a aplicação e o banco compartilham um mesmo sistema de arquivos. Elasusam bancos locais ou arquivos para armazenar dados em um fomato conhecido normalmente comoflat-file format. As aplicaçÕes que usam esta arquitetura simples são muitas vezes denominadasaplicações “desktop”, pois compreende tanto os elementos da interface como o mecanismo que seráusado para interfacear com o banco de dados, como o BDE, DBExpress ou ADO. Veja na figura abaixoum exemplo da lógica da arquitetura de 1 camada.

Aplicações de duas camadas

O desenvolvimento de aplicações com duas camadas (two tiered application) provê um suporte muitomaior ao acesso concorrente de muitos usuários aos seus dados e permite-lhe usar servidores debancos de dados remotos que podem armazenar uma quantidade de informação muito grande. Emaplicações de 2 camadas, uma aplicação cliente interage diretamente como um servidore de banco dedados remoto. Neesta arquitetura, todas as aplicações são clientes de um servidor de dados e, por isto,é também chamada de “modelo Cliente/Servidor” (Client/Server model). Um cliente requisita e enviainformações para o servidor remoto, e um servidor pode processar requisições de muitos clientessimultaneamente, coordenando o acesso e atualização dos dados. A imagem abaixo mostra a estruturade uma aplicação de 2 camadas que usa ADO para se comunicar com o servidor remoto.

FiguraX- Modelo de uma aplicação de uma camada que usa a BDE para acessar dados.

Page 124: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

124

Aplicações multi-camadas

Quando as informações de um banco de dados incluem complicados relacionamentos entre muitastabelas, ou quando o número de usuários de seu banco é bastante grande, você pode optar pordesenvolver seu aplicativo usando uma arquitetura mais flexível, conhecida como arquitetura de multi-camadas (multi-tiered application). Aplicações multi-camadas incluem servidores de dados (middletiers) que centralizam a lógica que governa as interações com seu banco de dados, promovendo umcontrole centralizado sobre os relacionamentos dos dados. Isto permite que aplicações clientes usem osmesmos dados enquanto asseguram que a lógica dos dados continua consistente. Esta arquiteturatambém que os aplicativos clientes sejam menores, mais rápidos, mais fáceis de serem instalados e dese manter, pois a maior parte dos processamentos e validações conhecidos comumente pela expressão“lógica comercial” está a cargo do servidor de dados. Aplicações multi-camadas também possibiliatamum ganho de desempenho de seus aplicativos ao providenciar uma distribuição do processamento dedados entre vários sistemas.Por padrão, uma aplicação multi-camadas é particionada em peças que residem em diferentesmáquinas. Este particionamento permite uma completa distribuição de tarefas em uma equipe dedesenvolvimento, uma vez que é possível estabelecer um plano de desenvolvimento dos aplicativos deforma totalmente independente para cada uma das equipes de desenvolvedores.Em um esquema mínimo, uma arquitetura multi-camadas comporta 1 aplicativo clientes, 1 aplicativoservidor de dados e 1 servidor de banco de dados remoto:

• O cliente provê a interface com o usuário para manipulação dos dados. Ele passa todas asrequisições de dados e envia atualizações para o servidor de dados.

• A aplicação servidora de dados (também chamada de remote data broker) comunica-sediretamente com o servidor remoto de banco de dados ou algum outro dataset ligado a um banco.

• O servidor remoto de banco de dados (SGDB) é responsável pelo gerenciamento de acessos,validações dos dados etc. É um servidor SQL.

Você deve desenvolver no Delphi os 2 primeiros elementos. Embora este exemplo ilustre uma situaçãomínima, devemos notar que a situação mais comum é existirem mais de um servidor de dados comfinalidades específicas, o que provê uma distribuição de carga ainda mais customizada.As aplicações clientes podem usar uma variedade de protocolos (TCP/IP, HTTP, DCOM, MTS ou Corba)para comunicar-se com o servidor de dados. O protocolo usado sempre depende do tipo de conexãoque o cliente usa para se comunicar com a aplicação servidora e do tipo de módulo de dados remotoque a aplicação servidora utiliza. Normalmente, muitos clientes se comunicam com uma únicaaplicação servidora, mas cópias de uma mesma aplicação servidora podem ser instaladas em mais deuma máquina para que se propicie uma grande distribuição de carga entre os diversos clientes e

FiguraX – Modelo de um aplicativo de 2 camadas que acessa uma fonte de dados via ADO.

Page 125: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

125

algumas aplicações servidora rodando em computadores diferentes. A figura abaixo ilustra a lógicageral deste modelo de acesso.

A evolução das arquiteturas de acesso

Ao longo dos anos a arquitetura de acesso a dados sofreu grandes mudanças. Podemos verificar hojeque, do esquema de acesso de um terminal “burro” atés os mais complexos aplicativos multi-camadashojes existentes houve uma grande evolução, e muitas tecnologias novas foram sendo desenvolvidas.Este tópico analisará rapidamente como esta evolução de arquiteturas se deu, aprofundando osdetalhes referentes a arquiteturas multi-camadas mais novas.

Terminais burros e aplicativos Desktop

Inicialmente, a arquitetura de acesso a dados existente era muito simples. Era uma arquitetura deapenas uma camada (single tier). Esta arquitetura era dominada pela poderosa presença dosmainframes, estes dinossauros da informática. Em essência, a arquitetura dominada pelos mainframesdeterminava que todo o processo de manipulação dos dados de aplicaçÕes ou bancos de dados estavaexclusivamente a cargo de um super-computador, que era o mainframe. Este trabalho era feito deforma rápida pelo mainframe, uma vez que haviam simples telas exibindo e entrando dados,denominadas comumente terminais “burros”. De fato, o terminal burro não era capaz de fazer nada,enquanto o mainframe fazia todo o trabalho, o que era facilmente aceitável, pois:

1. O mainframe é usualmente um poderoso computador;2. A quantidade de dados processados então era pequena, se comparada às demandas de nossos

dias.

O diagrama abaixo ilustra o funcionamento de uma arquitetura de uma camada dominada por ummainframe.

Posteriormente, esta arquitetura foi adaptada para computadores com capacidade de armazenamentode dados de bancos de dados e aplicativos. Estes computadores trabalhavam isoladamente, com oarmazenamento local de dados. Os PC’s foram se destacando, desta forma, como opções mais viáveispara informatização de dados.

Figura XDiagrama representandoum típico modelo de umacamada dominado por ummainframe.

Page 126: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

126

Aplicativos Client/Server

Quando ocorreu esta mudança do suporte da arquitetura de uma camada, com o advento do PC,percebeu-se que os dados já não eram mais compartilháveis, como, de uma forma muito diferente, oeram em um mainframe. Foi esta a necessida básica que fez surgir o modelo cliente/servidor(client/server). Em essência, o modelo de acesso cliente/servidor age de forma a colocar a fonte dosdados de um banco de dados em um local acessível a todos os computadores clientes. Um dosbenefícios deste modelo é o fato de um computador mais potente (denominado servidor) hospedarigualmente o sistema de banco de dados, o que lhe dá maior velocidade nas respostas das requisiçõesdos clientes; mas os clientes, por sua vez, também estavam encarregados de algum processamento, ejá não eram simplesmente terminais “burros”. O modelo cliente/servidor trabalha, então, sob umaarquitetura de duas camadas, que pode ser entendida claramente através do diagrama que segue:

O modelo cliente/servidor trabalhou por muitos anos (e ainda trabalha!), e foi muitas vezesconsiderado um solução ideal.

Os problemas começaram quando o volume de dados manipulados pelas aplicações foi se tornandomuito grande. E, por mais que novos equipamentos mais potentes fossem surgindo, o problemacontonua a presistir. Então, por que isto aconteceu? Se olharmos o funcionamento dos mainframes,vemos que eles poderiam manipular a quantidade de dados que o modelo cliente/servidor não podemanipular. Por que? A razão óbvia que explica este acontecimento está relacionada às redes detrabalho dos computadores. O mainframe apenas transportava sinais de tela para os terminais burros,isto é, apenas a informação necessário na hora certa. Por sua vez, o modelo cliente/servidor lida com

FiguraXRepresentação deuma arquiteturade duas camadasusando ummodelocliente/servidor.

Figura XDiagrama representandoum típico modelo de umacamada em um PC.

Page 127: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

127

estes dados de uma maneira muito diferente, e que exige muito mais carga de rede. Algumas técnicasforam implementadas então para minimizar o problema dos acessos concorrentes em rede, tais comoreplicações e sincronização de dados.

Contudo, nos dias de hoje percebe-se que o modelo cliente servidor está claramente esgotado.

Aplicativos distribuídos

A arquitetura multi-camadas foi desenvolvida pensando em resolver os problemas da arquitetura deduas camadas do modelo cliente/servidor. A solução encontrada baseou-se na preservação dasmelhores características das arquiteturas de uma e duas camadas:

1. Os clientes deveriam receber apenas os dados que eles precisariam, e somente quando fornecessário. Estes clientes forma denominados thin clients (clientes leves).

2. A camada intermediária deveria manipular os dados, validá-los e postá-los no servidor.

A camada intermediária centraliza a lógica que governa suas interações com o banco de dados, deforma que haja um controle centralizado nos relacionamentos dos dados. Isto permite que diferentesclientes usem os mesmos dados, ao mesmo tempo que é assegurada uma consistente lógica namanipulação dos dados. Torna possível, também, o desenvolvimento de clientes muito leves e maisfáceis de serem instalados e configurados.

Com o advento de acessos remotos a informações de bancos de dados, com o particionamento dosdireitos de acesso a aplicativos em muitos grupos diferentes de usuários, bem como o enormecrescimento do uso de páginas html dinâmicas que acessam bancos de dados, a arquitetura multi-camadas foi definitivamente implantada como novo modelo de desenvolvimento. As aplicações multi-camadas são também denominadas aplicações distribuídas devido ao fato de a lógica geral de umaaplicação estar dividida em diversas camadas independentes.

Uma outra abordagem da arquitetura multi-camadas é aquela que identifica a funcionalidade de cadacamada.

• Uma camada de dados;• Uma camada de regras dos dados das aplicações ;• Uma camada de apresentação.

Page 128: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

128

Nas aplicações de uma camada, todos os três aspectos são manipulados pela aplicação. Nas aplicaçõesde duas camadas (como um aplicativo cliente/servidor), um servidor de dados manipula os dados euma aplicação cliente manipula as regras dos dados e a apresentação.

Por que escrever aplicações distribuídas?

A distribuição de uma aplicação não é um fim em si mesmo. As aplicações distribuídas introduzem umconjunto de novos conceitos de desenvolvimento e distribuição. Algumas aplicações são intrinsicamentedistribuídas: jogos multi-usuários, Chat’s e aplicações de teleconferência são exemplos deste tipo deaplicações. Nestes casos, os benefícios de uma infraestrutura robusta de computação distribuída sãoóbvios. Muitas outras aplicações são também distribuídas, no sentido de que possuem ao menos duasaplicações sendo executadas em máquinas diferentes.

Uma aplicação distribuída pode acomodar diferentes clientes com diferentes capacidades, ao rodaralguns componentes no lado cliente quando possível ou rodá-los no lado servidor quando necessário.Aplicações distribuídas são também muito mais escaláveis do uma outra que não o seja.Se toda a lógica de uma aplicação complexa está contida em um único módulo, existe apenas umamaneira de aumentar o desempenho sem se rever a aplicação: um hardware mais rápido. Em umaaplicação distribuída, esta pode ser a última solução a ser adotada.

A tecnologia DataSnap

FiguraXRepresentação de uma arquitetura de múltiplas camadasusando um modelo de acesso remoto.

Page 129: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

129

DataSnap é uma tecnologia da Borland que permite o envio de dados (em pacotes) em um rede decomputadores comum, em uma rede distribuída ou em um sistema de arequivos local. Em essência,DataSnap é responsável pelo empacotamento, armazenamento e envio de dados em qualquer situação.Esta tecnologia é usada pelos datasets clientes, em combinação ou não com outros componentes detransmissão de dados. DataSnap provê as capacidades de aplicações multi-camadas permitirem aaplicaçÕes clientes conectarem a provedores em uma aplicação servidora. O suporte oferecido peloDelphi para desenvolvimento de aplicações multi-camadas é uma extensão da maneira como osdatasets clientes comunicam-se com um componente provedor, usando dados em pacotestransportáveis.Uma vez que você tenha entendido como criar e manipular uma aplicação de três camadas, você podecriar e adicionar camadas de serviços, conforme a sua necessidade.

Entendendo aplicações que acessam providers

O suporte oferecido pelo Delphi para criação de aplicações distribuídas consiste em um conjunto decomponentes das páginas DataSnap e DataAcess da palheta de componentes, mais um conjunto deoutros objetos criados a partir da página “multitier” do Repositório de Objetos. Em síntese, eles estãobaseados na capacidade de componentes provedores empacotarem dados em pacotes transportáveis emanipular atualizações recebidas como pacotes de dados transportáveis.

Os tipos de componentes necessários à criação de um aplicativo multi-camadas é descrito na tabelaabaixo:

Componentes Descrição

Módulos de dadosremotos

Módulos de dados especializados que podem agir como um objeto COM Automation, servidor SOAP ouCORBA que fornecem aos clientes acesso aos provedores nesles contidos. Tais objetos são usados naaplicação servidora.

Componentesprovedores

Agem como um data broker que provê dados criando pacotes de dados e resolvendo atualizações dosclientes. São usados na aplicação servidora.

Datasets clientes Datasets especializados que usam a biblioteca midas.dll para manipular dados armazenados em pacotes.Os datasets clientes são usados nas aplicações clientes.

Componentes deconexão

Uma família de componentes que localizam o servidor, estabelecem conexões e tornam interface COMIappServer acessível aos datasets clientes. Cada componente de conexão é especializado no uso de umdeterminado protocolo de comunicação.

Os protocololos da DataSnap

Existem muitos tipos de componentes de conexão que posem conectar um dataset cliente a umaaplicação servidora. Todos eles são descendentes de TCustomRemoteServer, e diferem primariamentequanto ao protocolo de conexão que cada um deles usa - DCOM, CORBA, TCP/IP, HTTP, ou SOAP.

O componente de conexão estabelece uma conexão para a aplicação servidora e retorna um interfaceIappServer que os datasets clientes podem usar para requisitar dados aos provedores. Aqui nóstocamos em um ponto importante: a primeira consideração a ser feita quando você iniciar odesenvolvimento de uma aplicação distribuída é qual será a tecnologia que será usada nas chamadasdos procedimentos remotos. Chamadas de procedimentos remotos (remote procedures called – RPC) éo termo usado para definir a tecnologia de chamada remota de procedimentos ou funções.

Page 130: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

130

COM, DCOM e COM+

Nós podemos criar uma aplicação servidora baseada nas tecnologia COM/DCOM/COM+ usando umRemote Data Module ou um Transactionl Remote Data Module. Esta metodologia usa as tecnologiasCOM e COM+ do Windows para invocar chamadas em um domínio Windows NT. Você pode tambémusar estas tecnologia sem Ter um servidor de domínios Windows NT instalado.

Vantagens:

• É o mais rápido protocolo da plataforma Windows;• Pode ser usado com outras aplicações COM da Microsoft ou de outros fornecedores;• Pode ser usado como um Servidor Transacional (MTS/COM+).

Desvantagens

• Pode ser de difícil configuração;• Não é compatível com sistemas operacionais que não pertençam `a família Windows.;• Perde algumas funcionalidades quando não estiver sendo executado em um domínio Windows NT;• Baixa portabilidade.

Quando usar

• Houver um grande número de clientes previstos• Houver necessidade de integração com outros objetos COM, tais como ActiveX ou servidores ASP;• Domínios NT’s fechados (sem WAN ou acessos de internet);• Velocidade for fundamental;• Portabilidade for secundário.

FiguraXA estrutura deatividade docomponente deconexãoTDCOMConnection.

Page 131: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

131

CORBA

Nós podemos riar uma aplicação servidora baseada em CORBA usando um CORBA Data Module. Aconexão a esta aplicação servidora é feita através de um componente TCORBAConnection. Aimplementação DataSnap usa o VisiBroker como OSAgent, para que as aplicações automaticamentetenham um balanço de carga e uma implementação de segurança contra falhas.

Vantagens

• Independência de locação;• Tratamento automático de falhas;• Fácil escalonamento do balanço de carga;• Fácil configuração;• Portábilidade a outros sistemas operacionais;• Alta escalabilidade.

Desvantagens

• Necessita de uma subnet TCP/IP;• Custo pode ser aumentado;• Não conversa com aplicativos Microsoft.

Quando usar

• Grandes implementações;• Portabilidade é importante;• Escalabilidade é requerida;

FiguraXO esquema de ação docomponente deconenxãoTCORBAConnection

Page 132: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

132

TCP/IP (Sockets)

O componente TSOcketConnection usa uma implementação COM/COM+ existente através de um proxyconhecido como Socket Server. Esta implementação é uma solução da Borland que trabalha no sentidode prover as conexões dos clientes ao servidor de dados através de uma porta TCP/IP conhecida comosocket. Deve ser lembrado que este protocolo foi intencionado como sendo uma última solução. Estaabordagem conhece algumas limitações, principalmente no que diz respeito à degradação do tráfegode rede e limite de clientes conectados. Para uma informação completa, consulte a ajuda do Delphi.

Vantagens

Como usa COM, pode ser usado em uma implementação COM já existente;Fácil conexão a partir de uma conexão remota ou pela internet;Fácil configuração;Pode ser segura com o uso de um interceptador.

Desvantagens

• Dependência do COM;• Usa entrada de ponto simples. Socket ocupado será bloqueado;• Baixo desempenho global;• Não trabalha com DCOM ou objetos COM remotos;• Dependente de locação.

Quando usar:

• Acesso remoto ou discado é requerido;• Implementações mais leves.

FiguraXO esquema de ação docomponente de conenxãoTSocketConnection

Page 133: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

133

HTTP (WEB)

O componente TWEBConnection usa uma implementação múltipla de uma conexão DCOM, um servidorWEB e um navegador WEB. Ele trabalha com o mesmo princípio de um proxy em uma conexão socket,mas não usa uma porta TCP/IP e sim um IIS Web Server. Os clientes usam um browser paratransportar requisições HTTP request/response. Este componente pode fazer uso de muitos recursos deautenticação de segurança da internet. Este protocolo também deveria ser usado como última opção.É, contudo, muito mais seguro e flexível queuma conexão usando simplesmente sockets, pois osclientes não precisam discar na sua rede, mas usam qualquer conexão de internet. Isso significa queum cliente pode estar em qualquer lugar do mundo e ainda estar apto a usar a sua implementação.

Vantagens

• Como usa COM, pode ser usado com um objeto COM já existente;• Conexão muito fácil na internet;• Fácil configuração;• Muito seguro (com IE para IIS SSL);

Desvantagens

• Dependente do COM;• Usa ponto de entrada simples. Um WEB Server ocupado bloqueará o acesso;• Pode ser uma conexão lenta;• Dependente de uma implementação WEB.

Quando usar

• Conexão através da internet é requerida;• Implementações leves que usam a internet como backbone.

FiguraXO esquema de ação do componente de conenxão TWEBConnection

Page 134: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

134

Entendendendo datasets

A unidade fundamental para acesso a dados é a família de objetos dataset. Sua aplicação usa datasetspara rodo acesso a banco de dados. Um objeto dataset representa um conjunto de registros de umbanco de dados organizados em uma tabela lógica. Estes registros podem ter sua origem em umaúnica tabela ou podem representar o resultado da execução de uma consulta sql ou de uma storedprocedure.Todos os datasets que você pode usar descendem de TDataset, e eles herdam campos de dados,propriedades, eventos e métodos implementados por esta classe.

O que é um TDataset?

TDataset é um dataset virtualizado, o que significa que muitas de suas propriedades e métodos sãodefinidas como virtual ou abstract. Um método virtual é uma declaração de função ou procedimentocuja implementação pode ser sobrescrita nas implementações de objetos descendentes. Um métodoabstrato é uma declaração de função ou procedimento que não conhece uma implementação ao nívelda classe do método abstrato. A declaração é um protótipo que descreve o método (e seus parâmetrose valores de retorno se houverem) que devem ser implementados em todos os descendentes deTDataset, mas que podem ser implementados de maneira diferente em cada um dos descendentes.

TDataset define muito do que é comum a todos os objetos datasets. Por exemplo, TDataset define aestrutura básica de todos os dataset: um array de campos (objetos TField) que correspondem acolunas em uma ou mais tabelas, campos lookup ou campos calculados.

Famílias de datasets

TDataset possui muitos descendentes imediatos, cada um correspondendo a um diferente mecanismode acesso a bancos de dados. Você não trabalha diretamente com qualquer um destes descendentesdiretos, pois cada um deles implementa uma grande quantidade de propriedades e métodos que sãoadequados especificamente para um mecanismo de acesso a dados e cada um destes métodos epropriedades são expostos para classes descendentes que são adapatadas para diferentes tipos dedados.Os descendentes imediatos de TDataset são:

• TBDEDataset, que usa o Borland Database Engine (BDE) para se comunicar com fontes dedados. Os descendentes de TBDEDataset que você usa são TTable, TQuery, TStoredProc eTNestedTable.

• TCustomADODataset, que usa ActiveX Data Objects (ADO) para se comunicar com uma fonte dedados OLEDB. Os descendentes de TCustomADODataset que você usa são TADODataset,TADOTable, TADOQuery e TADOStoredProc.

• TCustomSQLDataset, que usa DBExpress para se comunicar com servidores de banco de dados.Os descendentes de TCustomSQLDataset que você usa são TSQLDataset, TSQLTable, TSQLQuery eTSQLStoredProc.

• TIBCustomDataset, que se comunica diretamente com um servidor de banco de dados Interbaseou Firebird. Os descendentes de TIBCustomDataset que você usa são TIBDataset, TIBTable,TIBQuery e TIBStoredProc.

Page 135: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

135

• TCustomClientDataset, que representa os dados de um outro dataset ou dados de um arquivoem disco. Os descendentes de TCustomClientDataset que você usa são TClientDataset (que seconecta a uma fonte externa de dados) e outros datasets especializados em um particularmecanismo de acesso.

Como a VCL provê uma grande flexibilidade na estruturação de novos descendentes de TDataset, vocêpode criar seu próprio descendente de TDataset, por exemplo para recuperar dados de uma planilhaeletrônica ou um dataset de memória. Existem também uma infinidade de descendentes de TDataset,disponíveis em pacotes de componentes, e que possuem características específicas para acessar umtipo de banco de dados através de mecanismos diferentes. Como a programação para banco de dadosé um dos tipos de desenvolvimento mais comuns, existe uma enorme quantidade de datasetsdisponíveis que você pode instalar para testar suas funcionalidades.O diagrama de classes abaixo mostra uma visão completa da família de datasets usadas pelo Delphi 6.

Tipos de datasets

No item acima, vimos todos os datasets classificados pelos métodos que eles usam para acessar dados.Você pode classificá-los também pelos tipos de servidores de dados que eles representam. Sob esteponto de vista, existem três classes básicas de datasets:

• Table-type datasets: tables-type datasets representam uma única tabelas do banco de dados,incluindo todas as linhas e todas as colunas. Dentro deste tipo de datasets encontramos Ttable,TADOTable, TSQLTable e TIBTable. Embora table-type datasets possam ser úteis e eficientes emmuitas situações, seu uso é mais recomendado quando você precisar trabalhas com bancos dedados locais.

• Query-type datasets: query-type datasets representam um comando SQL, ou consulta. Consultaspodem representar o resultado de um comando executado (tipicamente uma DML). Estes tipos de

FiguraX – Diagrama de hierarquia dos objetos descendentes de TDataset.

Page 136: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

136

datasets podem também executar comando que não retornam qualquer resultado (por exemplo,um comando INSERT ou UPDATE). Entre estes tipos de datasets encontramos Tquery, TADOQuery,TSQLQuery e TIBQuery. Estes tipos de datasets forma desenvolvido para serem usados comservidores de dados SQL, mas alguns mecanismos de acesso podem processar uma consulta SQLsobre bancos locais. Use sempre estes datasets quando trabalhar com servidores SQL, tais comoInformix, Interbase ou Oracle.

• Stored procedure-type datasets: stored procedure-type datasets representam um procedimentoarmazenado (stored procedure) em um servidor SQL remoto. Entre os datasets inclusos nestacategoria estão TStoredProc, TADOStoredProc, TSQLStoredProc e TIBStoredProc.

Além destas categorias, existem dataset que se enquadram em mais de uma categoria ao mesmotempo:• TADODataset e TSQLDataset têm uma propriedade CommandType que permite-lhe especificar

se eles representam uma tabela (table), consulta(query) ou um procedimento armazenado (storedprocedure).

• TClientDataset representa os dados de um outro dataset e, como tal, pode representar umatabela (table), consulta(query) ou um procedimento armazenado (stored procedure).TClientDataset também pode conter uma consulta SQL que pode ser utilizada como qualquerconsulta deste tipo.

• Alguns outros client datasets (TBDEClientDataset e TSQLClientDataset) têm uma propriedadeCommandType que age da mesma forma como nos datasets acima descritos.

• TIBDataset pode representar tanto consulta(query) como um procedimento armazenado (storedprocedure). De fato, este dataset pode representar múltiplas consultas e procedimentosarmazenados simultaneamente em propriedades separadas para cada um deles.

Nota: para usar query-type datasets você deve estar familizarizado com a linguagem SQL e muitas dassuas subdivisões como DML ou DDL.

Usando os eventos de TDataset

Datasets têm eventos que habilitam uma aplicação perfazer validações, computar totais e muitas outrastarefas. Todos os eventos têm um comportamento uniforme em todos datasets. A tabela abaixo forneceuma lista dos eventos disponíveis com uma sucinta descrição:

Evento DescriçãoBeforeOpen / AfterOpen Chamados antes / após o dataset ser abertoBeforeClose / AfterClose Chamados antes / após o dataset ser fechadoBeforeInsert / AfterInsert Chamados antes / após o dataset entrar em estado de inserçãoBeforeEdit / AfterEdit Chamados antes / após o dataset entrar em estado de ediçãoBeforePost / AfterPost Chamados antes / após as alterações serem gravadasBeforeCancel / AfterCancel Chamados antes / após as alterações serem canceladasBeforeDelete / AfterDelete Chamados antes / após um registro ser deletadoOnNewRecord Chamado quando um novo registro é inserido; use para iserir valores padrãoOnCalcFields Chamado quando campos calculados são calculados

Além destes eventos, alguns client datasets implementam eventos específicos:

Evento DescriçãoBeforeApplyUpdates /AfterApplyUpdates

Chamados antes / após o dataset aplicar as atualizações a um provider

BeforeExecute / AfterExecute Chamados antes / após o dataset executar um comandoBeforeGetparams/ AfterGetParams Chamados antes / após o dataset receber parâmetros de um providerBeforeRowRequest /AfterRowRequest

Chamados antes / após o dataset transferir informações sobre o novo registro

Page 137: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

137

OnReconcileError Chamado quando um dataset precisa reconciliar erros ocorridos durante atuaizações.

Page 138: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

138

CC AA PP ÍÍ TT UU LL OO 11 00 -- TT RR AA BB AA LL HH AA NN DD OO CC OO MM AA BB DD EE

A Borland Database Engine (BDE) é mecanismo de acesso a dados que pode ser compartilhado pordiversas aplicações. A BDE define uma poderosa biblioteca de chamadas de API que podem criar,reestruturar, trasferir dados, atualizar e manipular tanto bancos de dados locais como servidores debanco de dados remotos. Para isto, a BDE provê uma interface uniforme de acesso a uma grandevariedade de servidores de bancos de dados, usando drivers que se conectam a diferentes bancos dedados.Dependendo da sua versão do Delphi, você pode usar drivers para bancos locais (Paradox, dBase,FoxPro e MSAcess), drivers SQL (SQL links) para servidores remotos como Interbase, Oracle, Sybase,Informix, Microsoft SQL Server e DB2, e um adaptador ODBC que lehe permite usar seu próprio driverODBC.

Quando você distribuir aplicações baseadas em BDE, você deve incluir o BDE com a sua aplicação. Istocertamenta aumentará o tamanho de seu programa de instalação, assim como a complexidade dadistribuição de seu aplicativo, mas a BDE pode ser compartilhada com outras aplicações nela baseadase prover um backgroung de suporte a aplicações de banco de dados bastante complexo.

Embora você possa usar chamadas diretas à API da BDE, os componentes da página BDE daComponent Pallete encapsulam a maior parte das funcionalidades para você.Este capítulo mostrará os conceitos mais importantes da programação de aplicações baseadas em BDE,bem como o significado e utilidade dos componentes que manipulam bancos de dados através destemecanismo.

Page 139: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

139

Conhecendo a BDE

A BDE consiste basicamente de um conjunto de arquivos e executáveis que formam um ambiente ouframework entre uma aplicação e um banco local ou servidor de dados. A BDE é responsável por ler,escrever e acessar os dados de seu banco de maneira completamente automática, isto é, sem que vocêtenha que se ocupar de implementar rotinas para fazer isto, como, por exemplo, usar chamadas deAPI de servidores de dados remotos. A BDE também providencia um mecanismo para que vocêconfigure de maneira fácil diversos detalhes referentes a como você irá acessar os dados, como astimeout de conexões, modos de leituras e escrita, linguagens internas de bancos a usar e muito mais.A BDE sabe como requisitar ou passar informações ao seu banco de dados e tratar dos muitos detalhesenvolvidos nestas operações. A BDE faz isto através de drivers especialmente desenvolvidos para secomunicar com um determinado banco de dados. Existem drivers BDE para qualaquer tipo de bancoque você deseje usar. Veja abaixo um esquema que ilustra a arquitetura de aplicações que usam BDEpara acessar dados:

Drivers usados pelo BDE

O BDE possui drivers para acessar tanto bancos locais como servidores de dados remotos. Estes driversconsistem em bibliotecas dinâmicas (dll’s) que acessam diretamente as rotinas necessárias paramanipular os mais diversos tipos de bancos. Estes drivers são classificados em 2 tipos:

• Nativos: são drivers que colocam as interfaces presentes no BDE em acesso direto a um banco dedados. Existem drivers nativos para acesso aos bancos Paradox, Dbase, MSAcess, FoxPro, Xbase,Oracle, Interbase, Firebird, Informix, MSSQL Server, DB2 e Sybase.

• ODBC: são drivers que colocam o BDE em contato com outro driver ODBC instalado em seusistema para realizar o acesso a um banco de dados.

Lembre-se apenas de que a maioria dos drivers ODBC instalados com o Windows são extremamentelentos e, com muita freqüência, pouco confiáveis. Além do mais, a tecnologia ODBC de acesso a dadosestá obsoleta e abandona pela própria Microsoft, que o substituiu por tecnologias bem mais avançadas,como OLEDB e ADO.Os drivers nativos são mecanismos rápidos e bastante confiáveis e têm sido tradicionalmente usados,desde a primeira versão da BDE, com sucesso.

Figura – Esquema geral de um aplicativo de uma camada que acessa dados usando a BDE

Page 140: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

140

O BDE Administrator

O BDE Administrator é uma ferramenta gerenciadora de conexões usadas pelo BDE. Com estaferramenta você pode criar um novo “Alias” (um nome para uma conexão com um banco de dados dedeterminado tipo), alterá-lo ou destruí-lo a qualquer instante. Os aplicativos que usam a BDE secomunicam com ela através deste “Alias”, e é possível examinar e alterar as configurações de cada umdos aliases em particular. Você pode também acessar as configurações gerais dos drivers instaladosacessando a página “Configuration” desta ferramenta. Mais a rente discutiremos o funcionamento desteaplicativo.

Suporte Delphi a aplicações BDE

O suporte Delphi a aplicações baseadas em BDE é fornecido principalmente por uma grandequantiodade de componentes que acessam de forma transparente os recursos disponíveis pelomiddleware. Estes componentes são datasets aptos para acessar qualquer tipo de banco de muitasformas diferentes. Existem também ferramentas que são instaladas com o Delphi e que auxiliammuitas tarefas comuns durante o desenvolvimento de um aplicativo BDE, como a criação de tabelas,índices etc de bancos de dados, análise dos dados de um banco ou monitoração e análise de acessos aservidores de dados remotos. Mais adiante estas ferramentas são citadas e detalhados os seus recursos.

Datasets baseados em BDE

Aplicações baseadas em BDE usam datasets específicos paraacessarem dados através desta tecnologia.Estes dadtasets herdam todas as capacidades implementadas com TDataset, sendo tambémimplementados propriedades, eventos e métodos novos que objetivam trabalhar com a BDE. Estesrecursos podem ser sumarizados nos seguintes pontos:

• Associação de datasets como objetos de conexão com banco de dados e controle de sessão deacesso,

• Processos de caching de dados BLOB’s;• Obtenção de um Handle de acesso ao BDE.

Existem três datasets baseados em BDE:

• TTable, um table-type dataset que representa todas as linhas e colunas de uma única tabela deum banco.

• TQuery, um query-type dataset que provê recursos de execução de consultas SQL.• TStoredProc, um stored procedure-type dataset que executa um procedimento armazenado de

uma servidor de dados SQL.

Nota: adicionalmente, TBDEClientDataset pode trabalhar como um dataset BDE normal, mastrabalha também como um client dataset.

Entendendo TDatabase e TSession

Para que datasets baseados em BDE possam recuperar dados de um servidor de dados remoto, elesprecisam trabalhar com um objeto TDatabase e com um objeto TSession.

Page 141: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

141

Tdatabse representa uma conexão para um servidor específico. Ele identifica um driver BDE, umservidor de dados que aceita este driver e um conjunto de parâmetros de conexão a serem passadosao servidor. Cada banco de dados é representado por um componente Tdatabase ao qual você podeassociar muitos datasets. Se os datasets de seu aplicativo não possuem um TDatabase associado, oDelphi criará dinamicamente um destes componentes e vinculará os datasets a ele. Você deveriasempre criar o seu próprio TDatabase, pois ele propicia um controle muito centralizado da conexão eseus parâmetros.Para associar um dataset BDE a um TDatabase, use a propriedade DatabaseName, que é uma stringque contem diferente informações, dependendo do tipo de banco de dados que você estiver usando.

Uma seção (session) provê gerenciamento global para um grupo de conexões com um banco de dadosem um aplicativo. Qhando você adiciona datasets baseados em BDE à sua aplicação, elaautomaticamente incluirá uma componente TSession denominado Session. À medida que você adicionadatasets em seu programa eles são automaticamente associados com este componente de seção“padrão”. Este componente também controla o acesso a a arquivos Paradox ou Dbase protegidos eespecifica localaizações de diretórios para arquivos Paradox compartilhados em uma rede. Você podecontrolar conexões com bancos de dados e acessos a arquivos Paradox usandos as propriedades,eventos e métodos de TSession.Alternativamente, você pode adicionar um componente TSession ao seu aplicativo em tempo de projeto(ou então criá-lo dinamicamente durante a execução de se aplicativo) para controlar um conjunto dedatasets. Para associar um dataset com um TSession explicitamente criado, use a propriedadeSessionName; porém, se você não provê um Tsession, você não deve inserir qualquer valor para estapropriedade. Para acessar um objeto TSession criado explicitamente ou não, use a propriedadeDBSession dos datasets.

Métodos de TDatabase e TSession

No geral, o componente Tsession providencia recursos globais que se aplicam a todos componentesTDatabase implicitmente criados. Por exemplo, a propriedade KeepConnection de Tsession determinase uma conexão feita por TDatabase é mantida se todos os datasets a ela vinculados são fechados.Similarmente, o evento OnPassword de objetos Tsession garante que uma caixa de diálogo de senhade acesso seja exibida toda vez que um usuário está prestes a estabelecer uma conexão com um bancoque exija validação de usuários.Os métodos de Tsession, por sua vez, agem sobre todas as conexões criadas por uma aplicação. Porexemplo, o método DropConnections fecha todos os datasets vinculados a uma conexão de banco dedados e, então, fecha todas as conexões, mesmo se a propriedade KeepConnection para umcomponente TDatabase em particular estiver definida como True.

Os métodos do componente TDatabase aplicam-se apenas para os datasets associados com umadeterminada instância de TDatabase. Suponha, por exemplo, que uma instância de TDatabase(Database1) está associada com um Tsession padrão.

Database1.CloseDataSets;

Fecha todos datasets associados com Database1.

Recursos avançados do BDE

Page 142: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

142

CACHING BLOBs

Todos os datasets baseados em BDE têm uma propriedade denominada CacheBlobs, que controla se osvalores de um campo BLOB são armazenados localmente pelo BDE. Por padrão, esta propriedadeboolean tem o valor True , o que significa que o BDE deve armazenar localmente uma cópia destesdados. O armazenamento local de dados BLOBs melhora o desempenho de um aplicativo, pois impedea leitura constante de uma fonte de dados à medida que o usuário navegaentre os registros de umdataset.Este recurso pode ser extremamente benéfico em aplicações que acessam servidores de dados remotosatravés de uma rede, pois diminui drasticamente o tráfego de rede ao longo de acessos a registros deum banco de dados.Em aplicaçÕes onde campos BLOBs são freqüentemente alterados ou uma visualização sempre atualdos dados de um campo BLOB é muito importante, você pode alterar o valor da propriedadeCacheBlobs para False, o que assegurará que se seu aplicativo sempre terá as últimas versões dosdados de uma campo BLOB.

Obtendo um handle BDE

Na maioria das aplicações BDE que você desenvolver não necessitará necessário fazer chamadasdiretas à API do BDE. A combinação de datasets, Tdatabase e Tsession encapsula a maior parte dasfuncionalidades deste mecanismo. Contudo, se você precisar fazer chamadas diretas à API do BDE,será necessário o uso de manipuladores (handles) de recursos gerenciados pelo BDE. Muitas funçÕes eprocedimentos da API do BDE requerem estes manipuladores como parâmetros.Todos datasets baseados em BDE incluem três propriedades não alteráveis para acessar handles BDEem tempo de execução:

• Handle é um manipulador para o cursor BDE que acessa os registros no dataset;• DBHandle é um manipulador para bancos de dados que contém as respectivas tables e

procedimentos armazenados.• DBLocale é um manipulador para drivers de linguagens da BDE. Estes recursos podem controlar a

ordenação de campos strings etc.

A estas propriedades são atribuídos valores automaticamente quando você conecta um dataset a umservidor de dados através da BDE.

Manipulando transações

Por padrão, a BDE provê um controle implícito de transações para suas aplicações. Quando umaaplicação está sob controle implícito de transações, uma transação separada é usada para cada registroem um dataset que é escrito em uma determinada base de dados. O controle implícito de transaçÕesgarante tanto um mínimo de conflito no processo de atualização do registro como uma visãoconsistente de um banco de dados. Por outro lado, devido ao fato de cada registro escrito tomar lugarem sua própria transação, o controle implícito de transações pode aumentar o tráfico na rede ediminuir o desempenho do aplicativo. O controle implícito de transações também impede a execuçãode operações lógicas que escrevem mais de um registro dentro de uma única operação validável(spanning).Se você controla explicitamente as transações, você pode escolher o mais efetivo momento de iniciar,confirmar (commit) ou revogar (roolback) suas transação. Quando você desenvolve aplicações em um

Page 143: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

143

ambiente multi-usuário e, particularmente, quando suas aplicações acessam um servidor SQL remoto,você deve controlar explicitamente as transações.Existem duas maneiras de controlar explicitamente as transações no BDE.

• Use o componente TDatabase para controlara as transações. A maior vantagem de usar estecomponente é o fato de propiciar um portabilidade `aua aplicação, independentemente do servidorSQL remoto que você deseja usar.

• Use passthrough SQL em um componente Tquery para passar consultas SQL diretamente para umservidor SQL remoto ou driver ODBC. A maior vantagem de passthrought SQL é que você podeusar o sistema de manipulação de transações de um servidor de banco de dados particular.

Nota: Quando você estiver trabalhando com bancos de dados locais, você não pode usar passthroughSQL.

É importante observar que o uso de transações em bancos de dados locais possui limitações; mas oBDE encapsula a maior parte das funcionalidades relacionadas ao uso de transações de formatotalmente automática.

Usando passthroug SQL

Com a técnica denominda Passthrough SQL você usa os componentes TQuery, TStoredProc ouTUpdateSQL para enviar uma rotina SQL de controle de transação diretamente para um servidor dedados remoto. O BDE não processa a rotina SQL a ser passada. O uso de passthrough SQL possibilita-lhe obter vantagens diretas do controle de transações oferecidos pelo seu servidor remoto.Para usar passthrough SQL é necessário configurar adequadamente o parâmetro de configuração“SQLPASSTHRU MODE” do sql link usado pelo BDE para o seu aplicativo. Para maiores informações,consulte a ajuda on-line do Delphi.

Usando transações locais

O BDE implementa um mecanismo de transações locais para bases de dados Paradox, dBase, Acess eFoxPro. Sob a perspectiva da codificação, não existem diferenças entre uma transação local e umatransação em um servidor SQL. Contudo, é claro que transações locais são muito mais limitadas:

• Recuperação automática de erros (Automatic crash recover) não é provido;• Recursos de definição de dados (DDL) não são suportados;• Transações não podem ser executadas em tabelas temporárias;• Para tabelas Paradox, transações só posem ser executado com índices válidos. Do contrário, os

dados não podem sofrer rollback;• Apenas um número limitado de registros podem ser travados e modificados. Em tabelas Paradox,

este limite máximo é de 255 registros. Em dBase, o limite máximo é 100;• Na configuração de seu Alias BDE, o perâmetro TransIsolation deve ser configurado apenas para

tiDirtyRead.

Ferramentas de trabalho com a BDE

Quando você necessitar trabalhar com o BDE, poderá usar diversas ferramentas que são distribuídascom o Delphi. Estas ferramentas incluem:

Page 144: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

144

• SQL Explorer.Esta ferramenta propicia um mecanismo de exame e manipulação muito detalhado da estrutura edos dados bancos de dados registrados na BDE. Você pode examinar as tabelas existentes; oscampos de cada tabela; os dados de cada tabela etc. Também é possível inserir ou alterar dados eexecutar consultas SQL em um banco de dados.Você pode criar atributos de objetos de bancos de dados, manipular um dicionário de dados; criarobjetos SQL tais como stored procedures em servidores SQL remotos etc.

• SQL MonitorEsta ferramenta de monitoramento e debugação permite o exame das comunicações feitas entreum servidor SQL remoto e o BDE.

• BDE AdministratorEsta ferramenta permite a você adicionar novos drivers de bancos de dados, configurara osexistentes e criar/manter alias BDE que apontam para bancos de dados.

Figura – O SQL Explores exibindo os dados de objetos de um banco de dados que é associado ao aliasatual.

Page 145: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

145

• Database DesktopEsta ferramenta permite a criação, edição e alteração da estrutura de tabelas Paradox ou dBase.Você pode também visualizar os dados de tabelas e editá-los.

O futuro da BDE

Em 2000, a Borland lançou um nova arquitetura de drivers SQL chamada “DBExpress”. A DBExpress édesenhada para propiciar alta performance no acesso a dados e simplificar a distribuição econfiguração de drivers SQL. A arquitetura DBExpress é destinada ao acesso a bancos SQL, e foidesenhada para ser altamente portável entre as plataforma Linux e Window. A DBExpress não usa aBDE.Esta nova arquitetura de drivers substitui a funcionalidade de acesso SQL a dados dos drivers SQL-linksdo BDE, mas o faz sem a necessidade de runtimes e outros objetos distribuídos que compoem o BDE.Atualmente, DBExpress é a solução de acesso recomendada pela Borland, que agora desaconselha aconstrução de aplicativos que acessam servidores sql remotos via BDE. A tecnologia de SQL links usadapelo BDE não sofrerá mais evoluções, de forma que a Borland hoje os considera “depreciados” ou“superados”, declarando publicamente que aconselha a migração para a tenologia DBExpress.Como o Delphi oferece diferentes mecanismos de acesso a banco de dados baseados em datasets, épossível realizar uma migração com um mínimo de alteração do seu código-fonte ou mesmo semalteração alguma, de forma que a Borland tem divulgado um esforço “mínimo” durante a migração.

Acesso a dados para tabelas locais

O BDE possui um grande suporte a bancos de dados locais, atis como Paradox, dBase e Acess. ABorland tem declarado que o suporte ao BDE como middleware de acesso a bancos de dados locais iráser continuado normalmente. Isto significa que o BDE será distribuído com as novas versões do Delphi,porém novos recursos não serão adicionados ao BDE, à exceção de correções de possíveis bugs.O resumo de tudo isto é que novos desenvolvimentos devem ser feitos sempre com bancos de dadossql e usando a tecnologia de alta performance DBExpress.

FiguraJanela principal do BDEAdministrator. Os aliasessão exibidos à esquerda,enquanto suasconfigurações aparecem nopainel maior à direita.

Page 146: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

146

Page 147: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

147

CC AA PP ÍÍ TT UU LL OO 11 33 -- AA PP LL II CC AA ÇÇ ÕÕ EE SS BB AA SS EE AA DD AA SS EE MM AA DD OO

Os componentes ADOExpress proveem acesso a dados através Microsoft ActiveX Data Objects (ADO)framework, um conjunto de objetos COM que acessam dados através de um provedor OLEDB. Oscomponentes ADOExpress encapsulam estes objetos em uma arquitetura de banco de dados. O layerde uma aplicação baseada em ADO consiste de Microsoft ADO 2.1, um OLEDB provider ou um ODBCdriver para acesso a fontes de dados, programas clientes para um sistema de banco de dadosespecífico (em sistemas de bancos de dados SQL) e o banco de dados. Tudo isto deve dever estaracessível para a aplicação baseada em ADO para que ela seja funcional.

Os objetos COM ADO mais proeminentes são Connection, Command e Recordset. Estes objetos ADOsão encapsulados pelos componentes TADOConnection, TADOCommand e alguns datasets. Oframework ADO incluem outros objetos auxiliares, como objetos “Field” e “Properties”, mas eles não sãotipicamente usados na implementação Delphi de acesso via ADO.

Neste capítulo você poderá perceber os principais aspectos desta tecnologia, bem como é possívelconstruir aplicações robustas acessando fontes de dados muito variadas, como uma planilha de dados,bancos MSAcess, MSSQL Server, Oracle ou Interbase. Porém, para compreender bem como ADOtrabalha e como você poderia retirar o máximo desta tecnologia, é indispensável um conhecimentobásico do modelo de objetos COM e DCOM do Windows, que é o fundamento real tanto deste sistemaoperacional como do framework ADO.

Page 148: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

148

A arquitetura ADO

A arquitetura ADO foi criada pela Microsoft dentro do escopo de uma estratégia maior dedesenvolvimento de tecnologias de acesso a dados conhecida como UDA (Universal Data Acess), quetambém engloba OLEDB e ODBC. Embora muitas destas tecnologias se confudam em alguns pontos, eODBC esteja em franco processo de depreciação e abandono, você deve compreender ADO como ummecanismo de acesso a dados que usa objetos COM (Component Object Model) e DCOM (DistributedComponent Object Model) que sabem como acessar um tipo de dado em paricular. Estes objetos COMsão acessados por outras aplicações através das interfaces que exportam, o que quer dizer quecolocam acessível ao mundo externo métodos e propriedades das suas interfaces.

ADO pode acessar diversos tipos de dados, pois, na verdade, constitui apenas um framework no qualas aplicações podem ser executadas e, muito especialmente, oferece um mecanismo complexo deisolamento de execução de aplicativos. Disto tudo, pode-se concluir que a tecnologia ADO tende a serrealmente universal, no sentido de que, sob seu ponto de vista, “dados” não são somente os registrosque podem ser recuperados de um determinado banco de dados, mas qualquer tipo de informaçãodisponível que um driver OLEDB consiga entender, tais como textos, documentos, sistemas de arquivos,informações do sistema operacional etc.

A tecnologia ADO também foi desenvolvida inicialmente pensando-se em uma arquitetura de softwaredistribuída, na qual ADO é apenas um invólocro agradável para a comunicação entre uma camada deaplicativo servidor e outra contendo as fontes de dados. No diagrama ao lado você pode perceberclaramente isto:

• ADO acessa uma fonte de dados através de um driver OLEDB que sabe como fazê-lo. O frameworkADO, por si, não sabe como poderia trabalhar com esta fonte de dados.

• A camada intermediária (business Process ou business tier) sabe como requerer de ADO umadeterminada informação, pois conhece os métodos exportados pelas interfaces dos objetos COM dodriver OLEDB.

Figura –Modelo da arquitetura deobjetos do Microsoft ADO.

Page 149: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

149

• A camada de interface (cliente) usa COM ou DCOM para se comunicar com a camadaintermediária, recebendo e enviando dados.

Você perceberá, ao longo dos próximos capítulos, que grande parte do suporte Delphi a banco dedados e, de uma forma mais ampla, a acesso a dados está voltado para o desenvolvimento deaplicações distribuídas. A tecnologia ActiveX Data Objects (ADO) é uma solução muito adequada a estetipo de desenvolvimento. Mas lembre-se: ADO é uma solução de todo dependente da plataformaWindows, embora o modelo distribuída permita-lhe sempre dividie as peças lógicas de umadeterminada aplicação em um ou mais sistemas operacionais.

Nota: a tecnologia COM, DCOM, ActiveX e suas derivadas serão estudadas no curso Delphi eTecnologias para Internet.

Tecnologia OLEDB

OLEDB é uma interface de programação a nível de sistema para acesso a dados. OLEDB é tambémuma especificação aberta, desenhada para acessar uma grande variedade de fontes de dados e, emúltima instância, qualquer tipo de dados, e pode acessar fontes de dados relacionais ou não-relacionais.Vários funções de sistemas gerenciadores de bancos de dados são encapsulados por OLEDB, que abilitaa criação de componentes de softwares implementados como servicos OLE. Os componentes consistemde provedores de dados (Data Providers), que contêm e expõem os dados; Data Consumers, que usamos dados; e services, que operam funções de agrupamento, ordenação de dados etc.Drivers OLEDB são objetos OLE existentes em bibliotecas dinâmicas que, uma vez registrados, podemser usados por qualquer aplicação que seja capaz de comunicar-se através do COM.Existem muitos drivers OLEDB desenvolvidos para fontes de dados diferentes, como bancos Acess,Oracle ou Interbase. Com Delphi, você também pode desenvolver seus próprios drivers OLEDB para asfontes de dados que desejar. A figura abaixo ilustra o mecanismo de funcionamento de um driverOLEDB através de interfaces de objetos COM.

Conhecendo a interface ADO

Microsoft ActiveX Data Objects (ADO) é uma interface de programação para dados a nível deaplicações para dados encapsulados junto a um driver OLEDB. ADO provê um consistente acesso a

FiguraEsquema geral de funcionamento deum provedor OLEDB. Através deinterfaces de objetos COM, eles secomunicam com a camada ADO que,por sua vez, transfere os dados paraum cliente ou um servidor de dados.

Page 150: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

150

dados em alta performance e suporta uma variedade de tarefas de desenvolvimento, como a criaçãode aplicações clientes de bancos de dados, objetos middle-tier de validação de regras comerciaisusadas pelas aplicações clientes ou navegadores WEB. ADO é desenhada para ser uma interface dedados necessária para aplicações de uma ou multi-camadas (incluindo aplicações servidoras baseadasna WEB). Um dos prncipais recursos implementados por ADO é oferecer uma interface deprogramação de fácil uso para alguns dos mais complexos aspectos do trabalho com drivers OLEDB.Como ADO oferece um mecanismo de acesso a objetos OLE/COM, você também pode usá-la comlinguagens de scripts.

Nota: ADO é instalado como padrão nos sistemas operacionais Windows98 em diante e substitui afracassada tecnologia ODBC.

A imagem abaixo mostra o modelo de objetos implementado com ADO.

Conhecendo a ADOExpress

A página ADO da palheta de componentes aramzena os componentes ADOExpress. Estes componentespermitem realizar uma conexão com uma fonte de dados ADO, executar comandos e retornar dados detabelas em bancos de dados usando o framework ADO. Você precisa ter instalado o Microsoft ADO 2.1(ou superior) em seu computador. Além disto, no computador on as aplicações clientes serãoexecutadas, para drivers OLEDB para o sistema de banco de dados a acessar também devem estarinstalados. Muitos componentes ADOExpress escontram componentes semelhantes disponíveis paraoutros mecanismos de acesso. ADOExpress disponibiliza um componente de conexão(TADOConnection) e vários tipos de datasets. Adicionalmente, ADOExpress inclui TADOCommand, umcomponente que não é um dataset, mas representa um comando SQL a ser executado. A tabela abaixolista os componentes ADOExpress:

FiguraModelo de objetos ADO implmentadospela Microsoft.

Page 151: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

151

Componente FuncionalidadeTADOConnection Estabelece uma conexão com uma fonte de dados ADO. Os datasets podem compartilhar uma mesma

conexão.TADODataset O componente primário usado para para retornar e operar sobre dados. Pode retornar dados de múltiplas

tabelas.TADOTable Usado para retornar e operar sobre dados produzidos a partir de uma única tabela.TADOQuery Usado para retornar e operar dados produzidos a partir de um comando SQL válido. Pode também executar

DDL.TADOStoredProc Usado para executar procedimentos armazenados de todos os tipos.TADOCommand Usado primariamentepara executar comandos SQL que não retornam dados.

Conectando com fontes de dados ADO

Para conectar sua aplicação com uma fonte de dados ADO, use o componente TADOConnection.Embora TADOConnection são seja estritamente requirido, pois TADOCommand e os componentesdatasets são capazes de estabelecer uma conexão direta usando a propriedade ConnectionString, vocêpode usar TADOConnection para compartilhar uma mesma conexão entre divesos componentes ADO.Isto pode reduzir o consumo de recursos, e permite a execução de transações em muitos datasets(spanning). Como outros componentes de conexão, TADOConnection provê suporte para:

• Controle de conexões;• Controle de login de usuários;• Manipulação de transações;• Trabalho com datasets associados;• Envio de comando ao servidor;• Obtenção de metadata.

Adicionalmente a estes recursos comuns a componentes de conexão, TADOConnection provê seupróprio suporte para:

• Grande quantidade de opções que você pode usar para ajustar o desempenho da conexão;• Capacidade de listar objetos de comandos que usam a conexão;• Eventos adicionais durante tarefas comuns.

Para compartilhar uma conexão entre muitos datasets, associe-os a um mesmo TADOConnectionatravés das suas propriedades Connection. Contudo, antes de você poder usar a conexão, é necessárioidentificar os parâmetros da conexão da ser feita. Tipicamente, você fornece estes dados através dapropriedade ConnectionString. Esta propriedade é uma string delimitada por ponto-e-vírgula (;) quelista um ou mais parâmetros de conexão. Os parâmetros indicam a fonte de dados a ser usada emuitos outros detalhes que podem diferenciar conforme o driver OLEDB utilizado.

Uma valor típico para esta propriedade é:

Provider=LCPI.IBProvider.1;Persist SecurityInfo=False;DataSource=c:\databases\ADOTeste\Projects.gdb

A maneira mais simples de configurar TADOConnection é acessando o editor disponível para apropriedade ConnectionString. Você pode ver na imagaem abaixo um imagem deste editor

Page 152: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

152

Este editor permite o acesso à janela de configuração de uma conexão com uma fonte ADO. Todo otrabalho de configuração de sua conexão é feito aí. Veja abaixo uma visão desta janela, com driverOLEDB SIBProvider, para acesso a Interbase, selecionado.

TADOConnection x Connection string

Cada dataset ou TADOCOmmand em um aplicativo pode ser conectado diretamente a uma fonte dedados. Contudo, quando numerosos datasets ou comandos são uisados, é sempre mais fácil trabalharusando um componente TADOCOnnection para estabelecer a conexão e compartilhá-la entre todosdatasets e comandos. O usode TADOCOnnection para estabelecer uma conexão oferece mais controlesobre a conexão do que conectar cada dataset individualmente.

FiguraJanela padrão do Windows para edição defontes de dados ADO. A imagem sómostra a página “Provedor”.

FiguraO editor de propriedades deConnectionString, que fazuma conexão com uma fontesde dados ADO.

Page 153: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

153

Logins e timeout

Você pode controlar o tempo válido para estabelecer uma conexão com um objeto TADOCOnnection. Apropriedade CommandTimeOut de TADOCOnnection estabelece o tempo máximo necessário paraconectar a uma fonte de dados. Se a conexão não for completada até o limite máximo determinado porCommandTimeOut, a conexão será considerada falha e cancelada. Configure ConnectionTimeOut como número de segundos após o qual a conexão será cancelada se não puder estabelecer uma conexãocom uma fonte de dados. Veja o fragmento de código abaixo que ilustra o uso de ConnectionTimeOut:

with ADOCOnnection1 do begin ConnectionTimeOut := 10;//10 segundos Open; end;

Ao tentar conectar um TADOConnection a uma fonte de dados, o evento de segurança OnLogin édisparado. Uma manifestação deste evento é o aparecimento de uma caixa de diálogo para o usuárioinserir seu nome e senha. Se você desejar, é possível suprimir esta caixa de diálogo e o nome dousuário e senha ser fornecido programaticamente.Para suprimir a caixa de diálogo padrão, primeiro configure a propriedade LoginPrompt para False.Então, forneça programaticamente as informações de acesso através da propriedade ConnectionString.Veja o fragmento de código abaixo:

with ADOCOnnection1 do begin LoginPrompt := False; ConnectionSTring := ‘Provider=IBProvider;Remote Server=PDC;UserName=João;Password=Cooperi’; Connected := True;

end;

Outra opção é fornecer as informações de login através de parâmetros do método Open. Veja:

with ADOCOnnection1 do begin LoginPrompt := False; ConnectionSTring := ‘Provider=IBProvider;Remote Server=PDC’ Open(‘João’,’Cooperi’); end;

Se você decide exibir a caixa de diálogo de login de usuário, mas o nome ou senha fornecidosestiverem incorretos, uma exceção do tipo EoleException é disparada.

Transações em ADO

Page 154: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

154

O componente TADOConnection inclui métodos e eventos para trabalhar-se com transações. Estascapacidades de trabalho com transações são compartilhadas por todos datasets baseados em ADO oucomandos que usam a mesma conexão com uma fonte de dados.

Usando métodos de transações

Use os métodos BeginTrans, CommitTrans e RollbackTrans para realizar processamento de transações.

• BeginTrans inicia uma transação na fonte de dados associada com o componenteTADOCOnnection;

• CommitTrans confirma uma transação atualmente ativa, salvando as mudanças no banco de dadose finalizando a transação.

• RollbackTrans cancela a transação atualmente ativa, abndonando todas as mudanças feitas durantea transação e finalizando-a;

Quando você precisar determinar se uma transação está em andamento, utilize a propriedadeInTransaction, que retornará True se ainda estiver em andamento e False no caso contrário.Uma transação iniciada por um componente TADOConnection é compartilhada por todos datasets ecomandos vinculados a ele.

Usando eventos de transação

O componente TADOConnection também oferece eventos para a manipulação de transações. Esteseventos indicam quando uma transação é iniciada, confirmada ou cancelada.

• OnBeginTransComplete é disparado quando uma transação for iniciada com sucesso.• OnCommitTransComplete é disparado após uma transação ser confirmada com sucesso.• OnRollbackTransComplete é disparado após uma transação ser cancela com sucesso.

Trabalhando com comandos

O conjunto de componentes ADO providos pelo Delphi permite a uma aplicação executar comandos. Noambiente ADO, comandos são representações textuais de uma ação de requisição a um provedorespecífico. Tipicamente, os comandos são rotinas SQL de Data Definition Language (DDL) ou DataManipulation Language (DML). A linguagem usada nos comandos é particular a cada um dosprovedores, mas, em geral, são usualmente compatíveis com o padrão SQL-92.

Os comandos podem ser executados a partir de mais de um componente Delphi. Cada componente decomandos executa-os de forma ligeiramente diferente. Qual componente você deve usar para umcomando particular é determinado pelo tipo de comando e pelo fato de retornar ou não um resultset.No geral, para comandos que não retornam um resultset, use o componente TADOCommand (apesarde TADOQuery também poder executar estes comandos). Para comandos que retornam um resultset,você pode usar um TADODataset ou um componente TADOQuery.

Page 155: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

155

Especificando o comando

O componente TADOCommand provê a abilidade de executar muitos comandos, mas sempre um decada vez. Foi desenhado primariamente para executar comandos que não retornam resultset de umaforma rápida e direta. Você informa o comando a ser executado através da propriedade CommandText,mas um comando pode ser também especificado através da propriedade CommandType.Em tempo de projeto, digite uma instrução SQL válida na propriedade CommanText de umTADOCommand através do Object Inspector. Em tempo de execução, atribua uma string a estapropriedades.Se desejar, defina explicitamente o tipo de comando a ser executado através da propriedadeCommandType. Entre as constantes disponíveis para esta propriedade temos:

• CmdText: usada para indicar que o comando é uma instrução SQL;• CmdTable: usada para especificar o nome de uma tabela;• CmdStoredProc: usada para especificar um procedimento armazenado.

Em tempo de projeto, especifique um valor adequdo para a propriedade CommandType. Durante aexecução do programa, atribua um valor tanto para a propriedade CommandType, como também paraCommandText. Veja um exemplo no fragmento de código que segue:

with ADOCommand1 do begin CommandText := ‘AddEmployee’; CommandType := cmdStoredProc; end;

Usando o método Execute

Quando você usar um componente TADOCommand, antes de um comando poder ser executado, eleprecisa estar conectado a uma fonte de dados. Uma vez que já o esteja, basta chamar o métodoExecute para executar o comando. Para comandos que não requerem parâmetros ou opções deexecução, chame a versão simples de Execute, que não possui quaisquer parâmetros. Veja um exemploabaixo:

with ADOCommand1 do begin CommandText := ‘UpdateInventory’; CommandType := cmdStoredProc; Execute; end;

Cancelando comandos

Após um comando houver sido executado (através do método Execute), é possível cancelar a suaexecução chamando-se o método Cancel. Por exemplo, veja o fragmento abaixo:

procedure TForm1.ExecuteButton.Click(Sender: Tobject);begin ADOCommand1.Execute;end;

procedure TForm1.CancelButton.Click(Sender: Tobject);

Page 156: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

156

begin ADOCommand1.Cancel;end;

O método Cancel somente tem efeito se houver um comando pendente e o comando for executado deforma assíncrona, isto é, se a opção eoAsynchExecute estiver no parâmetro do método Execute. Umcomando está pendente quando, após a chamada do método Execute, ele ainda não foi completado ouencerrado por um TimeOut.

Retornando dados com comandos

A execução de um comando que retorna dados é feita da mesma forma que a execução de comandosque não retornam, exceto que um componente ADO Dataset pré-existente deve representar o resultset.O método Execute do comando retorna um objeto ADO Recordset. Atribua este valor de retorno àpropriedade RecordSet de um dataset ADO, tal como um TADODataset.

No exemplo abaixo, o ADO Recordset produzido pela chamada do méodo Execute de um componenteTADOCommand é atribuído à propriedade RecordSet de um componente TADODataset:

with ADOCommand1 do begin CommandText := ‘select company, state from customer where state =:state’; CommandType := cmdText; Parameters.ParamByName(‘state’).Value := ‘HI’; ADODataset1.RecordSet := Execute;end;

Tão logo esta atribuição é feita, o dataset é ativado automaticamente e os dados estão disponíveis.

ADO.NET

Recentemente, a Microsoft tem lançado uma grande campanha de marketing para divulgação da suanova tecnologia e arquitetura para desenvolvimento de aplicações WEB, que foi denominada .NET. Estanova tecnologia é baseada basicamente na construção de WebServices e acesso a bancos de dados deforma desconectada. ADO.NET é o framework no qual toda tecnologia .NET de acesso a dados (nãoapenas bancos de dados) está baseada, em estreita ligação com o uso de XML como repositório dedados. Com efeito, todos os dados que um serviço .NET implementa são expostos via XML (tanto dadosde bancos de dados como atributos de campos, propriedades definidas pelo usuário etc).

Embora o estudo de tecnologias WEB seja assunto de capítulos posteriores, este tópico irá introduzirrapidamente alguns conceitos fundamentais sobre a tecnologia ADO.NET. Um estudo muito maisdetalhando sobre serviços WEB (WebServices) e ADO.NET será desenvolvido nos capítulos destinadosàs tecnologias WEB disponibilizadas pelo Delphi.

Page 157: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

157

A arquitetura ADO.NET

ADO.NET provê acesso consistente a muitas fontes de dados expostas via OLEDB e XML. As aplicaçõesque compartilham muitos dados podem usar ADO.NET para conectar a estas fontes de dados eretornar, manipular e atualizar dados através de provedores de dados .NET para conexão com bancosde dados. O framework de ADO.NET executa estas atividades através de objetos COM existentes embibliotecas como XML.dll e Data.dll que são primariamente desenhados para acessar dados emaplicativos multi-camadas, como em um WEBService. Embora, ADO.NET seja capaz de trabalharnormalmente com acessos locais a dados, sua intenção primordial é estabelecer uma camadaintermediária entre um cliente (front-end) e uma fonte de dados, configurando assim uma arquiteturade acesso em várias camadas lógicas “inter-relacionadas”. O mecanismo pelo qual ADO.NET transfereos dados recuperados de uma fonte de dados a um cliente, independentemente da sua origem ounatureza, é o XML. A figura abaixo ilustra como ADO.NET trabalha com uma fonte de dados e comclientes de diversos tipos, como um aplicativo Windows “comum” ou um aplicativo WEB e um ambientemulti-camadas.

Datasets ADO.NET

O objeto Dataset (não confundir com TDataset do Delphi) é um elemento central no suporte a cenáriosdisconectados e distribuídos característicos de ADO.NET. Dataset é uma representação de dadosresidentes em memória que provê um modelo relacional consistente de programação de acesso afontes de dados. Pode ser usado com fontes de dados múltiplas e diferentes, usadas com dados XMLou usado para manipular dados locais de uma aplicação. O objeto Dataset representa um completoconjunto de dados que incluem constrições, tabelas relacaionadas e relacionamento entre tabelas.

FiguraA arquitetura ADO.NET em umesquema multi-camadas típico.

Na camada deapresentação, vemosaplicativos clientes de diversostipos acessando dados de umacamada intermediária atravésde XML. Na camadaintermdiária, vemos objetosADO.NET que são responsáveispelo acesso à camada dedados.

Page 158: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

158

Provedores de dados .NET

Um provedor .NET é usado para conexão com um banco de dados, e pode executar comandos eretornar dados em um resultset. Este resultset tanto pode ser processado diretamente como tambémpode ser atribuído a um dataset ADO.NET, para que seja exibido ao usuário de uma maneiraadequada. Os provedores de dados .NET são desenhados para ser leves, criando um layer mínimoentre a fonte dos dados e seu aplicativo, aumentando performance sem sacrificar qualquerfuncionalidade.O framework .NET inclui um provedor de dados para MSSQL server 7.0 ou superior e um provedorOLEDB .NET. Outros provedores estão sendo adicionados constantemente para oferecer suporte aoutras tecnologias de acesso.

Você pode observar que ADO.NET não oferece nenhum mistério para um programador Delphi queconheça ADOExpress e, principalmente, que esteja acostumado com o desenvolvimento de aplicativosmulti-camadas. Na verdade, quando a tecnologia .NET dispontou, os programadores Delphi jádesenvolviam aplicativos multi-camadas com marshaling de dados via MIDAS e, conseqüentemente,XML. Caracteristicamente, a Microsoft formou acordo de parceria com a Borland para odesenvolvimento de todo o escopo do que hoje chamamos .NET e WebService. Em capítulosposteriores, estudaremos em profundidade estas tecnologias.

Page 159: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

159

CC AA PP ÍÍ TT UU LL OO 11 44 -- AA PP LL II CC AA ÇÇ ÕÕ EE SS II NN TT EE RR BB AA SS EE EE XX PP RR EE SS SS

A Interbase Express (IBX) é um conjunto de componentes de acesso a dados que provê ummecanismo que pode acessar, administrar, monitorar e rodar serviços no Interbase. A maior vantagemoferecida pelos componentes IBX é que eles podem acessar um servidor Interbase diretamente, sem anecessidade de um middle ware como o BDE. Este acesso direto se faz através de chamadas à API doInterbase, que são encapsuladas em objetos do Delphi para fácil manipulação. Isto certamenteaumenta o desempenho de um aplicativo, pois assim é possível livrar-se dos complicados mecanismosusados pelo BDE que geram um considerável “overhead” no acesso aos dados.

A IBX é capaz de acessar bancos Interbase ou Firebird, e está disponível para as plataformas Linux eWindows. Através deste conjunto de componentes, você pode desenvolver aplicativos, servidores WEBetc que permitem-lhe um controle direto e rápido de todas as funções e serviços disponibilizados porum servidor Interbase.

Este capítulo oferece uma visão geral do desenvolvimento de aplicativos usando a Interbase Express,mas parte do pressuposto de um conhecimento mínimo do Interbase e Sistemas Gerenciadores deBancos de Dados Relacionais (SGBDR). Certamente, você não precisa conhecer bastante o Interbasepara conseguir compreender como o Delphi oferece suporte a este servidor SQL remoto através daIBX.

Page 160: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

160

A arquitetura Interbase Express

A arquitetura dos componentes da biblioteca Interbase Express tem como forte característica acapacidade de acessar diretamente bancos de dados Interbase 6.0 ou Firebird 1.0 ou superiores. O fatode acessarem estes servidores SQL diretamente, significa que os componentes Interbase Express nãonecessitamde nenhum tipo de software para conseguir “conversar” com os servidores, mas simestabelecem este contato através dechamadas à API do Interbase/Firebird.

Como conseqüência deste acesso direto, a Interbase Express oferece o modelo de acesso mais rápido epoderoso a estes servidores. Além disto, você pode desenvolver aplicações IBX que acessam diversasfuncionalidades relacionadas à estatística de acesso, manutenção de servidores, serviços de backup etc.Estas funcionalidades são providas da mesma forma, isto é, através de acessos à API dos servidores.

Neste tópico, você conhecerá os componentes disponibilizados pela Interbase Express, bem como comousá-los para obter um rápido acesso a bancos de dados Interbase/Firebird.

Conhecendo a IBX

A Interbase Express (IBX) é um conjunto muito completo e flexível de componentes para acesso diretoa bancos de dados Interbase. Você não encontrará apenas componentes de conexão e datasetsdiversos dentro deste pacote, pois grande parte dos recursos de administração de um servidorInterbase/Firebird, monitoramento, controle de usuários, estatísticas de dados etc são encapsulados emdiversos componentes IBX. Sob o ponto de vista de suas funcionalidades, existem dois tipos básicos decomponentes IBX:

• Componentes relacionadaos a acesso e manipulação dos dados de um banco;• Componenes relacionados à administração de um banco e de um servidor Interbase/Firebird.

Certamente, você usará muito os componentes do primeiro tipo (englobam datasets, comandos ecomponentes de conexão e controle de transações), mas muitas outras funcionalidades podem serobtidas de maneira muito simples através de componentes de manipulação de servidores e bancos dedados.Este suporte completo às funcionalidades de um servidor SQL remoto é possível devido ao fato de oInterbase/Firebird possuirem uma arquitetura de software muito aberta, o que quer dizer, entre outrascoisas, que expõem todas as suas funcionalidades através de uma API de acesso bastantedesenvolvida. A tabela abaixo oferece uma descrição simples dos componentes encontrados naInterbase Express em sua versão 4.4.

Figura –A arquitetura dedatasets para acesso abanco de dados viaInterbase Express.

Page 161: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

161

Componente DescriçãoTIBDataBase Realiza a conexão entre a sua aplicação e o banco de dados InterBase.TIBTransaction É o responsável pelo controle de transações da sua aplicação. Você pode controlar transações concorrentes, ou

em threads independentes.TIBQuery Usado para fazer uma consulta SQL em a seu banco de dados InterBase. Este componente aceita quase todas

as instruções DDL, DML e DQL. Para utilizá-lo em modo live resultset, é necessário o uso do TIBUpdateSQL.TIBStoredProc Executa um procedimento armazenado no servidor InterBase.TIBUpdateSQL Permite definir instruções DML para cada método Insert, Edit e Delete. TIBUpdateSQL associado a um TIBQuery

representa toda a funcionalidade SQL de manipulação de Dados e live resultset.TIBDataSet Engloba toda a funcionalidade de TIBQuery+TIBUpdateSQL, e ainda é mais rápido. Seu uso é recomendado pelos

criadores dos componentes Interbase Express.TIBSQL Executa instruções ou comandos SQL. Recomendável para o uso de instruções DML ou DDL.TIBDataBaseInfo Retorna várias informações do seu banco de dados.TIBSQLMonitor Cria um LOG para acompanhamento de todas as instruções enviadas para o servidor.Trabalha em conjunto com

a propriedade TraceFlags de TIBDataBase.TIBEvents Captura eventos de um banco de dados InterBase. O Interbase é capaz de emitir eventos que podem ser

capturados por aplicações.TIBExtract Extrai informações de metadados das tabelas de sistemas, de usuário e todos outros objetos existentes em um

banco InterBase.TIBConfigService Envia e muda os parâmetros de um banco InterBase; entre eles, o Intervalo de Sweap, Page Control´s e outros.TIBBackupService Realiza uma operação de backup em um banco de dados.TIBRestoreService Restaura um backup feito anterirormente.TIBValidationService Valida a sua base de dados, como as transações em Limbo, as transações Default e outras validações.TIBStaticalService Mostra as estatísticas de um banco de dados; entre elas : Log, Header Pages, Índices e outras.TIBLogService Cria seu próprio LOG de um banco de dados InterBase.TIBSecurityService Gerencia o acesso a usuários ao seu banco Interbase, assim como a manutenção dos dados dos mesmos.TIBLicensingService Oferece recurso para a manutenção nos certificados de acesso do InterBase.TIBServerProperties Retorna informações de configuração do servidor InterBase.TIBInstall Oferece um mecanismo para instalar o InterBase, configurar os diretórios de instalação e os componente que

serão instalados.TIBUninstall Oferece um mecanismo para desinstalar os componentes usados na instalação do InterBase.

Herança baseada em TDataset

A arquitetura IBX é baseada na herança básica de TDataset. Isto significa que todos os métodos,eventos e propriedades com os quais você está acostumado a lidar como desenvolvedor de aplicativosde banco de dadados estarão disponíveis também nos datasets IBX. Como você pode observaranalisando a hierarquia de objetos IBX, os datasets herdam de uma classe genérica TIBCustomDataset.A partir dela, são criados datasets correspondentes a tabelas, consultas, procedimentos armazenados eoutros. Você não deve usar uma instância de TIBCustomDataset, mas sim de um dos seusdescendentes.Observe também que o uso de componentes baseados em tabelas (como é o caso de TIBTable) deveser feito com muito critério em bancos de dados SQL como o Interbase ou o Firebird. Sempre escolhaum componente capaz de trabalhar com consultas SQL.

O componente TIBSQL é capaz de executar comando em uma banco de dados com muita rapidez eeficiência. Você pode observar que ele não herda de TDataset, o que significa que não possui osrecursos implementados por esta classe que se referem à exibição e navegação de dados. TIBSQL édestinado a executar comandos DDL ou DML, mas não comandos DQL. Isto significa que TIBSQL éincapaz de obter um resultset de dados. As vantagens do uso de TIBSQL são evidentes quandopensamos que é possível executar comandos da maneira mais rápida possível no Interbase, com ummínimo de alocação de recursos.

TIBDataset é um componente diferente, pois dispoem em sí mesmo todos mecanismos pararecuperação e edição dos dados. Use-o para executar comandos SQL do Interbase/Firebird. Cadacomponente TIBDataset possui propriedades separadas para lidar com dados recuperados (tipicamenteatravés de um comando SELECT), para executar alterações nos registros, para inserir novos registros,

Page 162: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

162

para eliminar registros e para atualizar o resultset (refresh). TIBDataset criar um buffer local doresultset, tornando-o completamente rolável.

Datasets unidirecionais

Uma vez que os datasets IBX acessam um servidor SQL remoto, você deve considerar com cuidado oconsumo de recursos e o tráfego na rede demandado por suas aplicações. Por padrão, o resultsetcriado a partir de uma consulta a um banco de dados SQL é unidirecional e não aceita edição. Istosignifica que você não poderá rolar os dados recuperados para trás, mas somente para o próximoregistro; também não poderá alterar qualquer dado recuperado. Os servidores SQL usam estaestratégia como um mecanismo para enconomizar recursos e minimizar o tráfego em uma redecorporativa. Contudo, a IBX permite usar datasets bidirecionais e atualizáveis (live result set), tal comovocê pode observar em bancos de dados locais. Mas lembre-se sempre de usar estes recursos comatenção para que seu aplicativo não “atole” a rede com constantes fetch de dados desnecessários.

A técnica mais limpa consiste em usar datasets capazes de buferizar seus dados no cliente (comoTIBDataset e muitos client datasets). Além disto, procure sempre retornar o menor resultset possível emantenha suas transações curtas e rápidas.

Extensibilidade da arquitetura IBX

Uma das características marcantes da arquitetura IBX é sua forte extensibilidade. Com isto se querdizer que você pode facilmente criar novos componentes ou alterar algum existente para atender assuas necessidades. Um fator que contribui muito para esta característica é a própria arquitetura da APIdo Interbase/Firebird. Muitos objetos IBX encapsulam as funcionalidades expostas através desta API, evocê pode criar livremente novos componentes e classes que acesses esta API e os objetos de umbanco de dados Interbase.

Para ilustrar esta características vamos criar um novo componente Delphi que será adicionado àInterbase Express. Este componente possuirá a funcionalidade básica de trabalhar com Generators,que são objetos existentes nos bancos de dados Interbase. Um Generator é um objeto simples, e tem afunção básica de armazenar um valor inteiro que pode ser lido ou alterado. Como os generators sãoobjetos globais de um banco de dados, eles podem ser acessados em qualquer rotina que você possaescrever no seu banco (como Triggers ou Stored Procedures). Um uso típico de generators é para quese possa dar suporte a campos auto-incrementados em uma tabela, ou simplesmente como variáveisglobais de um banco de dados.

Nota: Embora a criação de componentes no Delphi esteja fora do escopo deste capítulo,introduziremos apenas os principais pontos que ilustram a extensibilidade da arquitetura da IBX eda própria API do Interbase/Firebird.

O componente será chamado TIBGenerator e derivará diretamente de TComponent. Ele terá asseguintes funções básicas:

• Ler um valor de um determinado generator;• Alterar um valor em um determinado generator;• Criar novos generators;• Deletar um determinado generator;• Listar os generators existentes em um banco de dado.

Page 163: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

163

TIBGenerator terá 2 propriedades importantes que temos de destacar.

• DatabaseName. É uma referência a um objeto TIBDatabase;• GeneratorName. É o nome de um generator;• Transaction. É uma referência a um objeto TIBTransaction que será usado nos métodos de

TIBGenerator.

As outras propriedades de TIBGenerator serão ignoradas por enquanto.

Como no Interbase todas as referências aos objetos de dados internos de um banco são armazenadasem tabelas especiais, denominadas “Tabelas de sistema”, TIBGenerator usará sempre um componenteTIBSQL interno para executar todas estas atividades descritas acima. Ou seja, ele fará todas asatividades acima usando rotinas DDL executadas por um objeto de comando da IBX, que é o TIBSQL.

Para ler um valor de um determinado generator, nós precisamos construir no Delphi um método deTIBGenerator que será chamado GetGeneratorValue. Este método é uma função que retorna uminteiro (o valor do generator de nome igual ao da propriedade GeneratorName). Para ser sucinto, ométodo conecta-se ao TIBDatabase assinalado e inicia uma transação com o objeto assinalado àpropriedade Transaction. O centro é o camando SQL GEN_ID que é uma função interna de todo bancoInterbase que altera/retorna o valor do generator. Veja o código abaixo:

function TIBGenerator.GetGeneratorValue: integer;var WasIntransAction: Boolean; IBSQL: TIBSQL;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction; try if not WasIntransAction then TransAction.StartTransaction; IBSQL := TIBSQL.Create(Self); try IBSQL.Database := FDatabase; IBSQL.Transaction := FTransAction; IBSQL.SQL.Text := Format('SELECT GEN_ID(%s, 0) FROM RDB$DATABASE',[GeneratorName]); IBSQL.ExecQuery; FValue := IBSQL.Fields[0].AsInteger; finally IBSQL.Free; end; result := FValue; finally if not WasIntransAction then TransAction.Commit; end; except FValue := -1; result := FValue; end;

end;

Page 164: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

164

O método DropGenerator deleta o generator GeneratorName do banco de dados através de umcomando DDL do tipo DROP. Veja o método abaixo:

procedure TIBGenerator.DropGenerator;var WasIntransAction: Boolean; IBSQL: TIBSQL;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction; try if not WasIntransAction then TransAction.StartTransaction; IBSQL := TIBSQL.Create(Self); try IBSQL.Database := FDatabase; IBSQL.Transaction := FTransAction; IBSQL.SQL.Text := Format('DELETE FROM RDB$GENERATOR WHERERDB$GENERATOR_NAME = %s' , [FGeneratorName]); IBSQL.ExecQuery; finally IBSQL.Free; end; finally if not WasIntransAction then TransAction.Commit; end; except SHowMessage(format('Write value operation to generator %s is failed!',[GeneratorName])); end;

O método AlterGenerator altera o nome de um generator e assinala um valor para ele:

procedure TIBGenerator.AlterGenerator(NewName: string; Value: integer);var WasIntransAction: Boolean; IBSQL: TIBSQL;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction; try if not WasIntransAction then TransAction.StartTransaction; IBSQL := TIBSQL.Create(Self); try IBSQL.Database := FDatabase; IBSQL.Transaction := FTransAction;

IBSQL.SQL.Add(Format('DELETE FROM RDB$GENERATOR WHERERDB$GENERATOR_NAME = %s' , [FGeneratorName]) + ';'); IBSQL.SQL.Add(Format('CREATE GENERATOR %s', [NewName]) + ';'); IBSQL.SQL.Add(Format('SET GENERATOR %s TO %d', [NewName,Value])+';'); IBSQL.ExecQuery; finally

Page 165: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

165

IBSQL.Free; end; finally if not WasIntransAction then TransAction.Commit; end; except SHowMessage(format('Update operation to generator %s is failed!',[GeneratorName])); end;

end;O método AlterGeneratorValaue altera o valor do generator GeneratorName:

procedure TIBGenerator.AlterGenereatorValue(Value: integer);var WasIntransAction: Boolean; IBSQL: TIBSQL;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction; try if not WasIntransAction then TransAction.StartTransaction; IBSQL := TIBSQL.Create(Self); try IBSQL.Database := FDatabase; IBSQL.Transaction := FTransAction;

IBSQL.SQL.Text := Format('SET GENERATOR %s TO %d', [FGeneratorName,Value]); IBSQL.ExecQuery; finally IBSQL.Free; end; finally if not WasIntransAction then TransAction.Commit; end; except SHowMessage(format('Write value operation to generator %s is failed!',[GeneratorName])); end;end;

O método ListGenerator insere o nome de todos os generators existentes em um banco em umaTStrings passada como parâmetro do método:

procedure TIBGenerator.ListGenerators(GenList: TStrings);var WasIntransAction: Boolean; IBQuery: TIBQuery; IDSystem: integer;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction; try

Page 166: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

166

if not WasIntransAction then TransAction.StartTransaction; IBQuery := TIBQuery.Create(Self); try IBQuery.Database := FDatabase; IBQuery.UniDirectional := True; IBQuery.Transaction := FTransAction; if FSystemGenerators = True then IDSystem := 1 else IDSystem := 0;

IBQuery.SQL.Add(Format(LstGenerators, [idsystem])); IBQuery.Open;

while not IBQuery.Eof do begin GenList.Add(IBQuery.Fields.Fields[0].AsString); IBQuery.Next;

end; finally

IBQuery.Close; IBQuery.Free; end; finally if not WasIntransAction then TransAction.Commit; end; except SHowMessage('List operation to generators is failed!'); end;

end;

Finalmente, o método CreateGenerator cria um novo generator com o nome contido na propriedadeGeneratorName no banco de dados:

procedure TIBGenerator.CreateGenerator;var WasIntransAction: Boolean; IBSQL: TIBSQL;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction; try if not WasIntransAction then TransAction.StartTransaction; IBSQL := TIBSQL.Create(Self); try IBSQL.Database := FDatabase; IBSQL.Transaction := FTransAction;

IBSQL.SQL.Text := Format('CREATE GENERATOR %s', [FGeneratorName]); IBSQL.ExecQuery; finally IBSQL.Free; end;

Page 167: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

167

finally if not WasIntransAction then TransAction.Commit; end; except SHowMessage(format('Write value operation to generator %s is failed!',[GeneratorName])); end;

end;

O importante a observar em todos estes métodos é o fato de usarmos objetos IBX para realizar todasestas tarefas através de comando DDL disponíveis na SQL do Interbase/Firebird. Você poderiaencapsular qualquer objeto de um banco de dados Interbase (tal como Exceptions ou Triggers) em umobjeto Delphi, e trabalhar de forma idêntica com eles. Segue-se abaixo o código-fonte completo daunidade que define TIBGenerator:

unit IBGenerator;

interface

uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,Dialogs, IBSQL, IBDatabase, IBCustomDataSet, IBQuery, SQLStrings;

type TIBGenerator = class(TComponent) private FGeneratorName: string; FSystemGenerators: Boolean; FValue: Integer; FDatabase: TIBDatabase; FTransAction: TIBTransAction; FAutoCommit: boolean;

procedure SetDatabase(const Value: TIBDatabase); procedure SetTransAction(const Value: TIBTransAction); function GetValue: Integer; procedure SetGeneratorName(const Value: string); procedure SetAutoCommit(Value: boolean); protected {}

public constructor Create(AOwner: TComponent); override; destructor Destroy; override; function Increment(const Step: Integer = 1): Integer; function GetGeneratorValue: integer; procedure DROPGenerator; procedure AlterGenerator(NewName: string; Value: integer); procedure AlterGenereatorValue(Value: integer); procedure CreateGenerator; procedure ListGenerators(GenList: TStrings); property Value: Integer read GetValue;

published property AutoCommit: boolean read FAutoCommit write SetAutoCommit; property Database: TIBDatabase read FDatabase write SetDatabase; property GeneratorName: string read FGeneratorName writeSetGeneratorName;

Page 168: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

168

property Transaction: TIBTransAction read FTransAction writeSetTransAction; property SystemGenerators: Boolean read FSystemGenerators writeFSystemGenerators; end;

procedure Register;

implementation

{ TIBGenerator }

procedure Register;begin RegisterComponents('Interbase', [TIBGenerator]);

end;

constructor TIBGenerator.Create(AOwner: TComponent);begin inherited Create(AOwner);end;

destructor TIBGenerator.Destroy;begin inherited Destroy;end;

procedure TIBGenerator.SetDatabase(const Value: TIBDatabase);begin

if Value <> FDatabase then beginFDatabase := Value;

if not Assigned(FTransAction) then FTransAction :=FDatabase.DefaultTransaction; end;end;

procedure TIBGenerator.SetTransAction(const Value: TIBTransAction);begin

if Value <> FTransaction then FTransaction := Value;end;

function TIBGenerator.GetValue: Integer;begin result := Increment(0);end;

procedure TIBGenerator.SetGeneratorName(const Value: string);begin

if not AnsiSameText(FGeneratorName, Value) then FGeneratorName := Value;end;

function TIBGenerator.Increment(const Step: Integer): Integer;var WasIntransAction: Boolean; IBSQL: TIBSQL;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction;

Page 169: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

169

try if not WasIntransAction then TransAction.StartTransaction; IBSQL := TIBSQL.Create(Self); try IBSQL.Database := FDatabase; IBSQL.Transaction := FTransAction; IBSQL.SQL.Text := Format('SELECT GEN_ID(%s, %d) FROM RDB$DATABASE',[GeneratorName, Step]); IBSQL.ExecQuery; FValue := IBSQL.Fields[0].AsInteger; finally IBSQL.Free; end; result := FValue; finally if not WasIntransAction then TransAction.Commit; end; except FValue := -1; result := FValue; end;end;

function TIBGenerator.GetGeneratorValue: integer;var WasIntransAction: Boolean; IBSQL: TIBSQL;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction; try if not WasIntransAction then TransAction.StartTransaction; IBSQL := TIBSQL.Create(Self); try IBSQL.Database := FDatabase; IBSQL.Transaction := FTransAction; IBSQL.SQL.Text := Format('SELECT GEN_ID(%s, 0) FROM RDB$DATABASE',[GeneratorName]); IBSQL.ExecQuery; FValue := IBSQL.Fields[0].AsInteger; finally IBSQL.Free; end; result := FValue; finally if not WasIntransAction then TransAction.Commit; end; except FValue := -1; result := FValue; end;

end;

procedure TIBGenerator.DropGenerator;var WasIntransAction: Boolean;

Page 170: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

170

IBSQL: TIBSQL;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction; try if not WasIntransAction then TransAction.StartTransaction; IBSQL := TIBSQL.Create(Self); try IBSQL.Database := FDatabase; IBSQL.Transaction := FTransAction; IBSQL.SQL.Text := Format('DELETE FROM RDB$GENERATOR WHERERDB$GENERATOR_NAME = %s' , [FGeneratorName]); IBSQL.ExecQuery; finally IBSQL.Free; end; finally if not WasIntransAction then TransAction.Commit; end; except SHowMessage(format('Write value operation to generator %s is failed!',[GeneratorName])); end;

end;

procedure TIBGenerator.AlterGenerator(NewName: string; Value: integer);var WasIntransAction: Boolean; IBSQL: TIBSQL;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction; try if not WasIntransAction then TransAction.StartTransaction; IBSQL := TIBSQL.Create(Self); try IBSQL.Database := FDatabase; IBSQL.Transaction := FTransAction;

IBSQL.SQL.Add(Format('DELETE FROM RDB$GENERATOR WHERERDB$GENERATOR_NAME = %s' , [FGeneratorName]) + ';'); IBSQL.SQL.Add(Format('CREATE GENERATOR %s', [NewName]) + ';'); IBSQL.SQL.Add(Format('SET GENERATOR %s TO %d', [NewName,Value])+';'); IBSQL.ExecQuery; finally IBSQL.Free; end; finally if not WasIntransAction then TransAction.Commit; end; except SHowMessage(format('Update operation to generator %s is failed!',[GeneratorName]));

Page 171: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

171

end;

end;

procedure TIBGenerator.AlterGenereatorValue(Value: integer);var WasIntransAction: Boolean; IBSQL: TIBSQL;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction; try if not WasIntransAction then TransAction.StartTransaction; IBSQL := TIBSQL.Create(Self); try IBSQL.Database := FDatabase; IBSQL.Transaction := FTransAction;

IBSQL.SQL.Text := Format('SET GENERATOR %s TO %d', [FGeneratorName,Value]); IBSQL.ExecQuery; finally IBSQL.Free; end; finally if not WasIntransAction then TransAction.Commit; end; except SHowMessage(format('Write value operation to generator %s is failed!',[GeneratorName])); end;end;

procedure TIBGenerator.CreateGenerator;var WasIntransAction: Boolean; IBSQL: TIBSQL;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction; try if not WasIntransAction then TransAction.StartTransaction; IBSQL := TIBSQL.Create(Self); try IBSQL.Database := FDatabase; IBSQL.Transaction := FTransAction;

IBSQL.SQL.Text := Format('CREATE GENERATOR %s', [FGeneratorName]); IBSQL.ExecQuery; finally IBSQL.Free; end; finally if not WasIntransAction then TransAction.Commit; end; except

Page 172: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

172

SHowMessage(format('Write value operation to generator %s is failed!',[GeneratorName])); end;

end;

procedure TIBGenerator.SetAutoCommit(Value: boolean);beginif FAutoCommit <> Value then FAutoCommit := Value;end;

procedure TIBGenerator.ListGenerators(GenList: TStrings);var WasIntransAction: Boolean; IBQuery: TIBQuery; IDSystem: integer;begin try Database.Connected := true; WasInTransAction := TransAction.InTransAction; try if not WasIntransAction then TransAction.StartTransaction; IBQuery := TIBQuery.Create(Self); try IBQuery.Database := FDatabase; IBQuery.UniDirectional := True; IBQuery.Transaction := FTransAction; if FSystemGenerators = True then IDSystem := 1 else IDSystem := 0;

IBQuery.SQL.Add(Format(LstGenerators, [idsystem])); IBQuery.Open;

while not IBQuery.Eof do begin GenList.Add(IBQuery.Fields.Fields[0].AsString); IBQuery.Next;

end; finally

IBQuery.Close; IBQuery.Free; end; finally if not WasIntransAction then TransAction.Commit; end; except SHowMessage('List operation to generators is failed!'); end;

end;

end.

Page 173: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

173

Compatibilidade inter-plataformas

Ao contrário de mecanismos de acesso como o BDE e ADO, a Interbase Express está disponível para odesenvolvimento de aplicativos para as plataformas Windows e Linux. Esta característica notávelpermite ao desenvolvedor compartilhar o mesmo código para gerar versões Linux ou Windows de seusaplicativos. É claro que todos os componentes Delphi que você adicionar à IBX (como o TIBGenerator)estarão também disponíveis para o desenvolvimento Linux e vice-versa (desde, é claro, que não usemrecursos específicos de uma plataforma).

Se você deseja escrever aplicativos inter-plataformas que acessem bancos de dados Interbase ouFirebird, a IBX é com certeza uma excelente escolha.

Page 174: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

174

Conectando com bancos de dados Interbase/Firebird

A IBX oferece um suporte muito completo de controle de conexões com bancos de dados Interbase.Este suporte é baseado no componente TIBDataset, que possui muitas propriedades, eventos emétodos relacionados aos mecanismos de conexão de um aplicativo com um servidor Interbase, taiscomo validação de usuários, character set, idleTimer etc. A maneira mais fácil de configurar umcomponente TIBDatabase é através de seu editor de propriedades, que oferece uma interfacecompleta para as suas opções. Veja, a seguir a tela do editor e a descrição das propriedadesfundamentais de TIBDatabase:

Propriedade DescriçãoDatabaseName É o nome do banco de dados no formato do endereço do arquivo principal do banco. Se o(s) arquivo(s) do

banco estiver em um outro computador, o endereço deve indicar o nome do computador.É importante observar o formato a ser

LoginPrompt Indica se uma caixa de diálogo para validação de acesso de usuário deve ser exibida.Params Esta propriedade é usada para passar ao servidor o nome do usuário, senha, SQLRole e character set a serem

usados.IdleTimer Indica quantos segundos o servidor deve esperar, quando uma conexão estiver inativa, para encerrar a

conexão.DefaultTransaction Objeto TIBTransaction que será usado como transação padrão da conexão.

Você acessa o editor de propriedades do componente TIBDatabase clicando com o botão direito domouse sobre um componente TIBDatase e, no menu de contexto quee se abre, escolher o item“Database Editor...”; ou simplesmente dando um duplo clique sobre um TIBDatabase.

Transações no Interbase

O Interbase e o Firebird são servidores SQL fortemente transacionais. Isto quer dizer que qualqueroperação que você fizer (como uma simples consulta SELECT ou uma DDL, por exemplo) deve ser feita

FiguraO editor de propriedades docomponente TIBDataBase.

Page 175: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

175

dentro do contexto de uma transação. Esta característica é uma exigência básica da arquiteturamuligeracional destes produtos. Este tópico discute como as transacões são tratadas pela InterbaseExpress.

Usando o TIBTransaction

Na Interbase Express, o componente central que você usa quando quer trabalhar com transações é oTIBTransaction, que é um descendente direto de TComponent. Todos os datasets ou comandos daInterbase Express precisam trabalhar com um TIBtransaction, pois os comandos SQL que executamdevem necessariamente estar encapsulados dentro do contexto de uma determinada transação. Vocêpode executar muitos comandos SQL dentro do contexto de uma mesma transação, mas receberá umamensagem de erro se tentar executar um SQL em uma transação inativa ou inexistente.

Ao escrever uma aplicação usando Interbase Express, você não precisa se preocupar com os detalhesreferentes à manipulação e gerenciamento de transações. Todos os datasets Interbase Express sabemcomo fazer todo o trabalho de inicialização de uma transação etc. Porém, muitas vezes você desejarácontrolar manualmente os processos de transações em seus aplicativos. Esta estratégia oferece o maiornível de controle sobre as transações de seu aplicativo. Para a execução destas tarefas o componenteTIBTransaction possui alguns métodos e propriedades.

• InTransaction• StartTransaction• Commit• Rollback• CommitRetaining• RollbackRetaining• Call

Níveis de isolamento de transações

O Interbase/Firebird oferece suporte a diferentes níveis de isolamento de transações. Os níveis deisolamento se referem à visibilidade oferecida dentro do contexto de uma transação diferente dareferenciada.

FiguraO editor de propriedadesdo objeto TIBTransaction.

Page 176: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

176

TIBTransaction também providencia, através da propriedade AutoSTopAction, um mecanismo paravocê determinar o que fazer quando uma transação for encerrada automaticamente . Considera-seuma transação é encerrada automaticamente, quando não receber uma instrução commit ou rollbackexplícita, como, por exemplo, quando você fecha um dataset IBX. Os valores possíveis para estapropriedade e o significado de cada um são os seguintes:

VALOR SIGNIFICADOsaNone A transação não será implicitamente encerrada.saRollback A transação será encerrada e todas as alterações serão desfeitas.saCommit A transação será encerrada e todas as alterações serão confirmadas.saRollbackRetaining A transação não é encerrada quando o dataset fecha, mas todas alterações, inserções, deleções de dados serão

desfeitas. Esta opção só é suportada pelo Interbase 6.0 ou superior ou o Firebird 1.0.saCommitRetaining A transação não é encerrada quando o dataset fecha, mas todas alterações, inserções, deleções de dados serão

confirmadas.

Esta propriedade apenas funciona quando os datasets são fechados. Se o objeto TIBTransaction estáassociado também a um componente TIBSQL, AutoStopAction deveria ser saNone, pois a transação nãopode determinar se um comando TIBSQL está ativo.

This property only works with the closing of TDataset descendants. If the transaction also includesTIBSQL components, AutoStopAction should be saNone, because the transaction can’t tell whetherthere are any active TIBSQL components.

Se você é um desenvolvedor de clientes de servidores SQL remotos, você deveria dedicar algum tempopara compreender bem como funciona uma transação nestes sistemas. Particularmente em servidoresSQL fortemente transacionais (como Oracle, Interbase e Firebird), é quase certo que você necessitarátrabalhar diretamente com o controle de transações. Uma vez dominado este conhecimento, vocêmesmo o considerará como um recurso indispensável em suas aplicações.

Trabalhando com comandos

Comandos são instruções SQL que você envia a um servidor remoto. A diferença básica entre umcomando e um dataset comum é que um comando não possui um link com uma TDataSource, o que otorna incapaz de estar ligado a controles de exibição de dados. Esta característica os torna a escolhaideal quando você deseja executar intruções SQL que não retornam um resultset, como se fazcomumente através de DDL ou DML. Este tópico abordará o suporte oferecido pela IBX para execuçãode comandos em servidores Interbase/Firebird.

O componente TIBSQL

O componente TIBSQL é caracterizado pelo fato de oferecer grande suporte à execução de comandos.Na verdade, TIBSQL foi desenhado unicamente para efetuar esta tarefa, e não pode trabalhar comoum dataset comum. Como se pode verificar ao observarmos a estrutura da IBX, TIBSQL não é umdescendente de TDataset, e não implementa nenhuma interface padrão para controles de dados, o quesiginifica que é incapaz de executar muitas tarefas ligadas à manipulação e cursores de dados. TIBSQLé também unidirecional.A grande vantagem de TIBSQL é o fato de ser capaz de executar comandos em um servidor SQL comum mínimo de consumo de recursos (overhead) e de forma muito rápida. Você sempre deveria usarum TIBSQL quando for executar qualquer instrução SQL que não retorne um resultset.

Page 177: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

177

TIBSQL implementa muitos métodos para o trabalho com comandos SQL. Citamos alguns deles natabela abaixo:

Método DescriçãoCheckValidStatement Dispara uma exceção se o comando a ser executa não conter uma instrução SQL válida.ExecQuery Executa a instrução SQL do comando.FreeHandle Libera os recursos do Interbase associados com uma consulta.Prepare Aloca recursos para execução otimizada de uma instrução SQL.

Muitos outros métodos estão disponíveis ainda para TIBSQL. Para uma referência completa consulte aajuda online da Interbase Express.

Executando comandos

O método ExecQuery do componente TIBSQL executa um comando SQL em um servidor Interbase. Aúnica coisa que você precisa se certificar antes de chamar este método é se seu TIBSQL possui umainstrução SQL válida atribuída à sua propriedade SQL e se está associado a uma transação. Como emmuitos casos você desejará tornar as alterações feitas por seu comando imediatamente disponíveis,você deve encerrar a transação após executar o comando. Veja o exemplo que segue:

procedure TForm1.BotaoExecuatarClick(Sender: Tobject);beginif not IBSQL1.Transaction.InTransaction then //Se não estiver iniciada... IBSQL1.Transaction.StartTransaction;//Inicia uma transação

IBSQL1.SQL.Clear;IBSQL1.SQL.Add(‘Delete from employee where custno = 2015’);IBSQL1.ExecQuery;//Executa o comando

IBSQL1.Transaction.Commit;//Confirma a transação

end;

Controlando um servidor Interbase

Adicionalmente a objetos de conexão, datasets, transações e comandos, a Interbase Expressdisponibiliza uma grande quantidade de componentes responsáveis pelo acesso a muitos serviços doInterbase/Firebird, tais como backup/restore, estatísticas, configurações de servidore,instalação/desinstalação etc. Este conjunto de componentes é conhecido com o nome “InterbaseAdmin”e está disponível desde a versão 4.0 da Interbase Express e só pode ser usado em servidores Interbase6.0, Firebird 1.0 ou superiores.Este tópico abordará alguns dos principais recursos expostos pela InterbaseAdmin.

A InterbaseAdmin

Com a InterbaseAdmin você pode ir muito além de criar um simples cliente Interbase. Os componentesoferecem suporte a praticamente qualquer serviço disponível em um servidor Interbase de maneira

Page 178: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

178

direta, sempre através de chamadas à API deste SGDB. Os componentes InterbaseAdmin são instaladospor padrão na página com o mesmo nome na palheta de componentes. A seguir daremos uma descrição simples da funcionalidade de cada um destes componentes:

Componente UtilidadeTIBConfigService Configura parâmetros de um banco de dados, como page buffers, async mode, reserve space e sweep interval.TIBBackupService Realiza um backup de um banco de dados. Todas as opções disponíveis em uma operação de backup são

encapsuladas por este componente.TIBRestoreService Restaura um backup de um banco. Todas as opções disponíveis em uma operação de backup são encapsuladas

por este componente.TIBValdationService Valida um banco e reconcilia transações. É possível configurar opções de validações, ações padrão de transações

e retornar informações de transações não encerradas.TIBStatisticalService Permite ver diversos dados estatísticos de um banco, tais como log, header pages, index pages, system relations

e data pages.TIBLogService Cria um arquivo de log.TIBSecurityService Permite manipular o acesso de usuário a um servidor Interbase. Com este componente você pode fazer qualquer

alteração nos usuário e roles de um servidor.TIBLicensingService Permite adicionar ou remover certificados de ativação de um servidor Interbase.TIBServerProperties Permite recuperar informações sobre um servidor Interbase.TIBInstall Permite criar aplicativos que instalem o Interbase com total controle de todas opções.TIBUninstall Permite criar aplicativos que desinstalem o Interbase com total controle de todas opções.

Você também pode criar qualquer novo componente que acesse um serviço de um servidor Interbase eadicioná-lo a esta coleção. Alguns destes componentes somente não possuem muita utilidade paradesenvolvedores de aplicativos clientes, enquanto outros são extremamente úteis. Se você desenvolveum aplicativo cliente, por exemplo, pode ser muito interessante oferecer uma maneira bastante fácil deoferecer uma instalação do Interbase que qualquer usuário possa realizar sem dificuldades. Umprograma que realize operações de backup de maneira muito simples para o susário comum é aindamais interessante. Na verdade, os componentes da InterbaseAdmin permitem a criação de um

aplicativo completo de gerenciamento e manutenção de um servidor Interbase, tal como o IBConsole,que é instalado com o servidor.

Você pode encontrar um exemplo de demonstração das funcionalidades de alguns dos componentes daInterbase Admin no diretório de instalação do Delphi “...Delphi6\Demos\DB\IBX\Admin\AdminTool.dpr”.A imagem abaixo mostra esta ferramenta de exemplo exibindo as propriedades de um banco de dados.

FiguraA ferramenta de exemplo da Borland“AdminTool” ilustra o uso de muitoscomponentes da palheta InterbaseAdmin.Na imagem ao lado você vê a janela

Page 179: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

179

Page 180: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

180

CC AA PP ÍÍ TT UU LL OO 11 55 -- AA PP LL II CC AA ÇÇ ÕÕ EE SS BB AA SS EE AA DD AA SS NN AA DD BB EE XX PP RR EE SS SS

DBExpress é um conjunto de drivers muito leves para acesso rápido a servidores de banco de dadosremotos. Para cada banco de dados suportado, a DBExpress provê um driver que se adapta a umservidor SQL específico e forma uma interface DBExpress uniforme. DBExpress permite o acesso abancos de dados usando datasets unidirecionais, que são desenhados para acesso rápido a dados deum banco, com um mínimo de overhead. Como outros datasets, eles podem enviar uma instrução SQLpara o servidor SQL remoto, e se esta instrução retornar um conjunto de dados, fornece um cursorpara o acesso a esses dados. Contudo, datasets unidirecionais podem retornar apenas um cursorunidirecional. Eles não “buferizam” os dados em memória, o que os faz mais rápidos e menoresconsumidores de recursos do que outros datasets. Muitas das capacidades implementadas em TDatasetestão também indisponíveis nos datasets unidirecionais, ou o seu dispara exceções. Por exemplo:

• Os únicos métodos de navegação suportados são Next e First. Todos os outros disparam exceções.Alguns métodos que envolvem bookmarks simplesmente não estão disponíveis.

• Não existe suporte para edição local de dados, pois isto requeriria um buffer de dados emmemória. Contudo, você pode atualizar dados de datasets unidirecionais usando comando SQL dotipo UPDATE ou prover mecanismos de edição através de datasets clientes.

• Não existe suporte a filtros, pois eles trabalham com múltiplos registros, o que requer um buffer dedados. Todas as limitações sobre quais dados devem aparecer devem ser feitos através decláusulas de comando SQL.

• Não existe suporte para campos lookup, que requerem um buffer de dados para armazenarmúltiplos registros contendo os valores dos campos lookup. Se você definir um campo lookup paraum dataset unidirecional, ele não funcionará adequadamente.

A despeito destas limitações, datasets unidirecionais são poderosos componentes de acesso a dados.Eles são o mais rápido mecanismo de acesso a dados, além de muitos simples de usar.

Este capítulo discutirá o funcionamento da DBExpress e o conjunto de datasets e outros objetos queela disponibiliza. Discutiremos também como você pode criar aplicações altamente flexíveis e quesuportam tanto a plataforma Linux quanto a Windows ao usar a tecnologia DBExpress.

Page 181: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

181

A arquitetura DBExpress

A DBExpress é um mecanismo de acesso a fontes de dados SQL. Você sempre deve Ter isto em mente,pois ela foi projetada com esta finalidade, e não oferece suporte a bancos de dados locais comoParadox ou MSAcess. Atualmente, a DBExpress é o mecanismo de acesso a dados que oferece omelhor desempenho e velocidade; e oferece isto sempre da mesma maneira, independentemente doservidor SQL que você desejar utilizar. Outra característica ímpar da DBExpress é a sua grandeportabilidade. De fato, usando a DBExpress você poderá criar aplicativos para Windows ou Linux,usando sempre o mesmo código-fonte.

Este tópico nos introduzirá os elementos mais importantes da arquitetura de objetos que usam aDBExpress como mecanismo de acesso a dados.

Como trabalha a DBExpress?

DBExpress é uma camada independente que define uma interface comum para provê rápido acesso aservidores SQL remotos. Para cada servidor suportado, DBExpress provê um driver na forma de umabiblioteca que implementa as interfaces DBExpress comuns para processar consultas e procedimentosarmazenados. Como uma camada leve e simples, DBExpress provê alto desempenho na conexão combancos de dados, alémde ser de distribuição muito simples. Como os drivers DBExpress estãodisponíveis no Windows como bibliotecas dinâmicas (dll’s), você precisa apenas distribuir esta bibliotecacom a sua aplicação.Existem drivers DBExpress para os seguintes servidores SQL:

• MY SQL• Interbase• Firebird• Oracle• Informix• Sybase• MS SQL Server• DB2

Os drivers DBExpress podem acessar um servidor SQL diretamente, através da sua API (como amaioria deles o faz) ou através de um outro mecanismo como ODBC, ADO ou BDE. Você deveria usarapenas drivers que fazem um acesso direto, pois de outra forma o Delphi já permite um acesso usandoestes outros mecanismos sem a DBExpress. Observe, igualmente, que se portabilidade entreplataformas é um fator importante no desenvolvimento de um aplicativo, alguns drivers DBExpress nãopodem ser usados, como qualquer um que acesse MS SQL Server ou aqueles que usem ODBC, ADO ouBDE para realizar acessos. Estes mecanismos e programas não possuem compatibilidade alguma com aplataforma Linux.

Tipos de datasets unidirecionais

A página DBExpress da Paheta de Componentes contém 4 tipos de datasets unidirecionais:

• TSQLDataset;• TSQLQuery;• TSQLTable;• TSQLStoredProc.

Page 182: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

182

TSQLDataset é o mais geral dos quatro. Você pode um TSQLDataset para representar qualquer dadodisponível através da DBExpress. Este é o componente atualmente recomendado para o trabalho combancos de dados.

TSQLQuery é um dataset baseado em consultas (query-type) e encapsula uma consulta SQL emanipulação de dados de retorno, caso estes existam.

TSQLTable é um dataset baseado em tabelas (table-type) que representa todas as linhas e colunas deuma única tabela.

TSQLStoredProc é um dataset baseado em procedimentos armazenados (stored procedure-type) queexecuta procedimentos armazenados em um servidor SQL.

Nota: Na página DBExpress também pode ser encontrado o componente TSQLClintDataset, quetambém é um dataset unidirecional. Iremos estudá-lo no tópico sobre datasets clients.

Conectando com um servidor SQL

O primeiro passo a ser dado quando você for trabalhar com datasets unidirecionais, é prover ummecanismo de conexão com um servidor SQL. Em tempo de projeto, desde que você tenha umaconexão ativa, o Object Inspector poder listas de valores para outras propriedades. Por exemplo, aotrabalhar com procedimentos armazenados, o Object Inspector pode listar aqueles que existem noservidor SQL para a sua escolha.A conexão com um servidor de dados é representada por um componente TSQLConnection. Vocêtrabalha com este componente da mesma forma com que trabalha com outros componentes deconexão. Em tempo de projeto, escolha qual conexão deseja efetuar a partir de uma lista disponível napropriedade SQLConnection de TSQLConnection. Tipicamente, todos os datasets unidirecionais de umaaplicação compartilham o mesmo objeto de conexão, a menos que você esteja trabalhando com dadosem múltiplos servidores SQL. Contudo, você pode quere usar um componente de conexão para cadadataset se o servidor de dados não suportar múltiplas consultas em uma única conexão. Assegure-sedeste fato através da propriedade MasxStmtsPerConn de um componente TSQLConnection.

Configurando o objeto TSQLConnection

Antes de você usar o componente TSQLConnection, é necessário configurá-lo adequadamente, a fim deque possa identificar o servidor de dados e realizar quaisquer operações requeridas em uma conexão,como a validação de senhas de usuários e identificação de drivers, por exemplo.

Identificando o driver

O driver usado em uma conexão é identificado atravésda propriedade DriverName, que é o nome deum driver DBExpress instalado, tal como : INTERBASE, ORACLE, MYSQL ou DB2. O nome do driver estáassociado com dois arquivos:

• O driver DBExpress, que pode ser tanto uma dll como uma unidade Delphi compilada.

Page 183: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

183

• O nome da dll provida para suporte DBExpress no lado cliente.

Especificando parâmetros de conexão

A propriedade Params é uma lista de strings com pares NAME/VALUE em cada uma des suas linhas,onde Name é o nome do parâmetro e Value é um valor a ele assinalado. Os parâmetros necessários àsua conexão dependem do servidor SQL que você está usando, mas o parâmetro Database é requeridopara todos os servidores. Por exemplo: com Interbase, Database é o nome de um arquivo .GDB; comOracle é a entrada no arquivo TNSMNames.ora etc. Outros parâmetros típicos incluem User_Name (onome do usuário ao efetuar um login), password (senha do usuário), HostName (o nome de umcomputador ou endereço IP etc) e TransIsolation ( o nível de isolamento das transações executadas noservidor).

Você pode inserir e alterar os valores da propriedade Params acessando o editor para edições devalores de listas desta propriedade. A imagem abaixo mostra este editor.

Nomeando uma descrição de conexão

Embora você possa sempre especificar uma conexão usando apenas as propriedades DatabaseName eParams de um componente TSQLConnection, pode ser mais conveniente nomear uma combinaçãoespecífica e passar a identificar a conexão diretamente por este nome. O nome de cada uma dascombinações quevocê criar são chamados “connection names”. Uma vez definido um “connectionname”, você pode identificar uma conexão DBExpress através da propriedade ConnectionName de umTSQLConnection. A atribuição desta propriedade automaticamente configura todos os detalhesnecessários a uma conexão.

A maneira mais simples de criar uma conexão DBExpress é através do editor de propriedadesConnection Editor. Em um só local você realiza todas as tarefaz de configurações necessárias demaneira muito rápida. Para exibir o Connection Editor, dê um duplo clique no componenteTSQLConnection. Este editor permite a criação e alteração de connections names, com todos os seusparâmetros. O editor exibe uma lista de drivers instalados, bem como todos os connection names jácriados. Através dos botões do editor, você pode criar novos nomes de conexão, deletá-los ou alterar

FiguraO editor de parâmtrosdocomponenteTSQLConnection.

Page 184: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

184

seus parâmetros. A imagem abaixo mostra o Connection Editor com muitos drivers e connectionsnames.

Especificando quais dados exibir

Existe algumas maneiras de especificar que dados um dataset unidirecional representa. O método quevocê pode usar depende do tipo de dataset usado e se as informações provêem de uma única tabelaou não. Quando você trabalha com o componente TSQLDataset, use a propriedade CommandType paraindicar onde o dataset recuperará os dados. Os valores possíveis para CommandType são:

• CtQuery. TSQLDataset executará uma consulta especificada por você. Se a consulta é umcomando SELECT, o dataset poderá conter o resultset.

• CtTable. TSQLDataset retorna todos os registros de uma tabela especificada.• CtStoredProc: TSQLDataset executa um procedimento armazenado. Se este procedimento

retornar um cursor, o dataset conterá os registros retornados.

Representando o resultado de uma consulta

O uso de uma consulta é o mecanismo mais genérico de se recuperar um conjunto de registros.Consultas são simplesmente comandos escritos em SQL. Você pode usar tanto um componenteTSQLDataset quanto um TSQLQuery para representar o resultado de uma consulta. Quando usar umcomponente TSQLDataset, configure a propriedade CommandText para ctQuery e escreva a consultaSQL na propriedade CommandText. Quando usar um componente TSQLQuery, apenas escreva aconsulta SQL na propriedade SQL. Estas propriedades trabalham da mesma maneira.

Representando os registros em uma tabela

FiguraO editor de conexõesDBExpress.

Page 185: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

185

Quando você quer representar todos os campos e todos os registros de uma única tabela, é possívelusar tanto um componente TSQLDataset quanto um TSQLTable para gerar uma consulta sem que vocêmesmo precise escrevê-la. Porém, nem sempre este apanhado é insteressante. Se o desempenho éuma questão importante em suas aplicações, quase sempre é melhor um apanhado diretamentemanipulado por você através de consultas otimizadas. Definitivamente, por mais que parece cômodo oseus usos, datasets baseados em tabelas não são adequados no acesso a servidores SQL.

O uso do componente TSQLDataset nestas situações, implica que o componente gerará uma consulta etransferirá todas as colunas e registros da tabela especificada. Apenas configure a propriedadeCommandType para ctTable. Quando CommandType possui este valor, o componente TSQLDatasetgera uma consulta baseado nos valores de duas propriedades:

• CommandText, que especifica o nome da tabela que TSQLDataset deveria representar;• SortFieldNames, que lista os nomes de todos campos a serem usados para ordenar os dados, em

ordem de maior importância. Por exemplo, se você especifica o seguinte:

SQLDataSet1.CommandType := ctTable;SQLDataSet1.CommandText := 'Employee';SQLDataSet1.SortFieldNames := 'HireDate,Salary'

TSQLDataset gera a seguinte consulta, que lista todos os registros na tabela Employee, ordenadospelos campos HireDate e, dentro da ordenação de HireDate, Salary:

select * from Employee order by HireDate, Salary

Representando uma tabela usando TSQLTable

Quando usar o componente TSQLTable, especifique a tabela que você deseja através da propriedadeTableName. Para especificar a ordenação dos campos no dataset, você deve informar um índice.Existem duas maneiras de se fazer isto:

• Configure a propriedade IndexName com o nome de um índice definido no servidor SQL;• Configure a propriedade IndexFieldNames como uma lista de nomes de campos, separados por

ponto-e-vírgula, que serão usados na ordenação.

Representado os resultados de uma stored procedure

Procedimentos armazenados (stored procedures) são conjuntos de instruções SQL que sãoarmazenadas em um servidor SQL. A maneira como você indica o procedimento armazenado a serusado depende do dataset unidirecional que você usa. Quando for usar um TSQLDataset, especifiqueum procedimento armazenado:

• Configurando a propriedade CommandType para o valaor ctStoredProc;• Especificando o nome do procedimento armazenado na propriedade CommandText.

Veja um exemplo no fragmento de código abaixo:

Page 186: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

186

SQLDataSet1.CommandType := ctStoredProc;SQLDataSet1.CommandText := 'MyStoredProcName';

Quando usar um componente TSQLStoredProc, é necessário apenas especificar o nome doprocedimento armazenado na propriedade StoredProcName.Após haver identificado um procedimento armazenado, sua aplicação pode precisar entrar com valorespara quaisquer parâmetros de entrada e/ou saída antes de executar o procedimento armazenado.

Obtendo os dados

Uma vez que você tenha especificado a fonte dos dados, é necessário recuperar os dados antes quesua aplicação possa manipulá-los. Como em qualquer dataset, existem duas maneiras de se obterdados nos datasets unidirecionais:

• Configurando a propriedade Active para True;• Chamando o método Open.

Contudo, existem algumas técnicas que podem otimizar estas operações.

Preparando o dataset

Antes que uma consulta ou procedimento armazenado possam ser executador em um servidor, elesdevem primeiro ser “preparados”. A “preparação” de um dataset significa que a DBExpress e o servidoralocm recursos para as instruções e seus parâmetros. Os datasets unidirecionais são automaticamentepreparados quando você configura a propriedade Active para True ou chama o método Open. Quandovocê fecha o dataset, os recursos alocados são liberados.

Se você precisa executar uma consulta ou procedimento armazenado mais de uma vez, ganharádesempenho ao preparar explicitamente o dataset antes de abrí-lo pel primeira vez. Para explicitamntepreparar um dataset, configure sua propriedade Prepared para True, como segue:

CustQuery.Prepared := True;

Os recursos alocados não serão liberados até que você configure a propriedade Prepared para False.

Transferindo dados de múltiplos datasets

Alguns procedimentos aramazenados retornam múltiplos conjuntos de registros. O dataset apenastransfere o primeiro conjunto quando você o abre. Para acessar os outros conjuntos de registros,chame o método NextRecordSet. Por exemplo, veja o fragmento abaixo:

varDataSet2: TSQLDataSet;nRows: Integer;

Page 187: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

187

beginDataSet2 := SQLDataSet1.NextRecordSet(nRows);...

O método NextRecordSet retorna um TSQLDataset criado novamente que prov6e acesso aos próximoconjunto de registros. Isto é, a primeira vez que NextRecordSet for chamado, retorna-se o terceirodataset e assim por diante até não haverem mais conjuntos de registros.

Executando comandos

Você pode usar datasets unidirecionais sempre que uma consulta ou procedimento armazenado nãoretornar um resultset. Tais comando, tipicamente, incluem DDL e DML. No caso de comandos, osdatasets meramente passam o comando para o sevidor SQL executar.

Contudo, estes comandos que não retornam dados não precisam ser executados por datasetsunidirecionais, pois não há necessidade alguma dos métodos deste componentes para manipulação dosdados. O componente TSQLConnection pode ser usado diretamente para executar comandos noservidor.

Métodos de execução

Para executar um comando com datasets unidirecionais, você não usa o método Open ou apropriedade Active. Neste caso, os métodos a serem usados são:

• O método ExecSQL, se o dataset é uma instância de TSQLDataset ou TSQLQuery. Veja o exemploabaixo:

FixTicket.CommandText := 'DELETE FROM Traffics WHERE (TicketID = 1099)';FixTicket.ExecSQL;

• O método ExecProc, se odataset é uma instância de TSQLStoredProc. Veja o exemplo:

SQLStoredProc1.StoredProcName := 'MyCommandWithNoResults';SQLStoredProc1.ExecProc;

Page 188: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

188

CC AA PP ÍÍ TT UU LL OO 11 66 -- AA PP LL II CC AA ÇÇ ÕÕ EE SS CC OO MM PP RR OO VV EE DD OO RR EE SS EE DD AA TT AA SS EE TT SS

CC LL II EE NN TT EE SS

Datasets clientes (client datasets) são datasets especializados que armazenam seus dadosem memória.O suporte à manipulação dos dados que eles armazenam na memória é provido pela unidadecompilada MidasLib.dcu ou pela biblioteca Midas.dll. O formato que os datasets clientes usam paraarmazenar dados é auto-contido e facilmente transportado, o que permite aos datasets clientes:

• Ler e escrever em arquivos dedicados no disco, agindo como um dataset baseado em arquivo;

• Armazenar as atualizações dos dados de um servidor de dados SQL;

• Representar os dados em um aplicativo cliente de aplicações multi-camadas. Para trabalhar destaforma, o dataset cliente deve trabalhar com um provedor de dados externo;

• Representar os dados provindos de uma outra fonte que não um dataset. Como os datasetsclientes podem usar os dados vindos de um provedor externo, provedores especializados podemadaptar uma variedade de fontes de informações que trabalham com datasets clientes. Porexemplo, você pode usar um provedor XML, a fim de permitir que um dataset cliente represente asinformações de um documento XML.

Se você usa um dataset cliente em bancos de dados baseados em arquivos, atualizações em cache,dados obtidos de um provedor externo (tais como os obtidos com um documento XML ou aplicaçõesmulti-camadas), ou uma combinação destes apanhados, como em um aplicativo de modelo porta-arquivos (briefcase), você pode obter vantagens através da grande quantidade de recursosimplementados em datasets cllientes para trabalhar com dados.

Este capítulo abordará toda a extensão do suporte Delphi a datasets clientes, esclarecendo as razões deesta tecnologia estar se tornando cada vez mais importante no desenvolvimento de aplicativosWindows.

Page 189: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

189

A arquitetura dos datasets clientes

As aplicações distribuídas introduzem um novo conjunto de conceitos de desenho, distribuição elogística que objetivam racionalizar as atribuições de operação e funcionalidades em diversosaplicativos, ao mesmo tempo que objetiva um acesso profundamente compartilhado dos dados. Desdeo surgimento dos primeiros aplicativos distribuídos, em grandes sistemas corporativos críticos e emmuitos serviços implementados via WEB, as grandes corporações fornecedoras de tecnologias dedesenvolvimento têm investido nas capacidades desta arquitetura de acesso. Particularmente a Borlande a Microsoft têm estado à frente nas pesquisas de tecnologia para implantação de aplicativosdistribuídos, o que resultou no fato de estas empresas terem desenvolvido tecnologias que hoje têm setornado padrão para o desenvolvimento de aplicações distribuídas. As grandes possibilidades hojecolocadas aos desenvolvedores através das tecnologias de WEBServices, SOAP e XML são fortesexemplos de como a Borland tem investido fortemente em tecnologias de aplicações distribuídas. Nosnossos dias a Borland detém reconhecida vanguarda e domínio mundial no desenvolvimento detecnologias para acesso distribuídos.

Por outro lado, a Microsoft já tem publicamente divulgado os seus planos de dotar paulatinamente osistema operacional Windows de recursos que ofereçam suporte a um ambiente de aplicativosdistribuídos. Inicialmente com DCOM e ActiveX e, mais recentemente, com o conjunto de tecnologiasdenominado .NET.

Como desenvolvedor Delphi, você só pode esperar avanços no suporte ao desenvolvimento deaplicativos distribuídos. Ano após ano, é principalmente nesta área que as novas versões do Delphi têmoferecido maiores novidades. Como desenvolvedor Delphi, você deve considerar, ainda, o fato de aBorland ser a parceira da Microsoft no desenvolvimento das tecnologias .NET. Este fato não só reforçao intuito — há muito público — da empresa focar seus esforços neste campo, como também abre deimediato a você uma perspectiva sedutora para os novos desenvolvimentos.

Neste tópico, você se introduzirá no suporte Delphi à criação de aplicações distribuídas que acessambancos de dados. Muitos aspectos não poderão ser discutidos agora, como aplicações distribuídas quesão executadas via WEB, CORBA, WEBServices, SOAP e aplicativos .NET. Todos estes assuntos (umaenormidade!) são objeto do curso que trata do suporte Delphi a tecnologias WEB distribuídas.

Estudando TClientDataset

TClientDataset é um componente dataset desenhado para trabalhar sem um suporte de conectividade.Tudo o que ele usa é a biblioteca MIDAS.dll. Este componente oferece todo o suporte a edição,navegação, constrição de dados e filtros oferecidos por muitos dos outros datasets, mas implementaseu próprio mecanismo de obtenção e atualização de dados. Isto é provido de uma das seguintesmaneiras:

• Lendo e escrevendo em um arquivo de dados (flat file) acessado diretamente.• Obtendo dados a partir de outros datasets.• Usando uma interface de acesso remoto para obter os dados e enviar as atualizações para um

aplicativo servidor de dados.

Estes mecanismos podem ser combinados de muitas formas diferentes, mas o comportamento geral deum TclientDataset será sempre semelhante.

Editando dados

Datasets clientes representam seus dados como um pacote residente na memória. Este pacote é ovalor da propriedade Data. Por padrão, contudo, as edições feitas nos dados não são armazenadas na

Page 190: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

190

propriedade Data. Ao contrário, todas inserções, deleções ou edições (feitas por usuários ouprogramaticamente) são armazenadas em uma espécie de log interno de mudanças, que é apropriedade Delta. O uso deste mecanismo serve a dois propósitos:

• Ao se trabalhar com um provider, o log de alterações é requerido pelo mecanismo que irá atualizaras mudanças no servidor de dados.

• Em qualquer arquitetura de aplicações com datasets clientes, o log provê um mecanismosofisticado para se desfazer alterações.

A propriedade LogChanges permite-lhe desabilitar temporariamente o recurso de log. QuandoLogChanges é True, as alterações serão registradas no log; do contrário, elas são feitas diretamente napropriedade Data. Você pode, por exemplo, desabilitar o recurso de log em uma aplicação de umacamada que não necessite desfazer as alterações.

As edições no log de mudanças permanecem até que sejam removidas pela aplicação, quando:

• Se desfazem alaterações;

• Salvam-se as mudanças.

Nota: Ao salvar-se registros em datasets clientes ligados a arquivos, o log de alterações não édesfeito. Isto oferece suporte a aplicações briefcase.

Desfazendo alterações

Datasets clientes são capazes de armazenar múltiplas entradas nos seus mecanismos de log demudanças. Isto significa que a cada alteração feita em um registro é gerada uma entrada específica nolog de alterações. Este armazenamento em separado torna possível o suporte a múltiplos níveis deoperações de desfazer, até o nível onde a primeira alteração foi feita.

Para remover a última alteração de um registro, chame o método UndoLastChange. Este método exigeo parâmetro FollowChange, do tipo boolean, que indica se se retornará o cursor no registro a serrestaurado. UndoLastCHange retorna um valor boolean, indicando se a operação de restauramento foifeita com sucesso ou não. Use a propriedade ChangeCount para conhecer o número de alteraçõesexistentes na propriedade Delta.

Você também pode remover todo o conteúdo do log de alterações, referentes a um determinadoregistro, de uma só vez, usando o método RevertRecord. Neste caso, o registro a ser considerado é oregistro atual.

Em qualquer ponto durante uma edição, você pode salvar o estado atual do log de mudanças usando apropriedade SavePoint. A leitura de SavePoint retorna um marcador dentro da posição atual do log.Mais tarde, se você desejar desfazer todas as mudanças que ocorreram desde a leitura do pontomarcado, configure SavePoint para o valor lido previamente. A sua aplicação pode obter valores paramúltiplos marcadores de pontos.

Page 191: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

191

É possível também abandonar todas as mudanças feitas chamando o método CancelUpdates. Destaforma, você limpa efetivamente o log de alterações. Seja cuidadoso ao usar CancelUpdates. Se vocêusá-lo inadivertidamente, não poderá obter novamente o log eliminado.

Salvando as alterações

Os datasets clientes usam mecanismos diferentes para incorporar as mudanças obtidas de um log dealterações, dependendo se eles são usados em uma aplicação stand-alone ou se representam os dadosobtidos de um servidor remoto. Independentemente do mecanismo usado, o log de alterações éautomaticamente esvaziado quando todas as atulizações são incorporadas.

Aplicações stand-alone podem simplesmente gravar as mudanças no cache de dados representado pelapropriedade Data. Não é necessário se preocupar com a manipulação de acessos concorrentes ouverificar alterações feitas por outros usuários antes de você. Apenas chame o métodoMergeChangeLog.

Você não pode usar este método em aplicações distribuídas. A aplicação servidora precisa dasinformações do log a fim de resolver possíveis conflitos de atualização. Use, então, o métodoApplyUpdates, que envia as mudanças para o aplicativo servidor e atualiza a propriedade Data apenasquando as modificações foram salvas com sucesso no servidor de dados SQL.

O método ApplyUpdates exige um parâmetro do tipo inteiro chamado MaxErrors. Este parâmetroinforma o limite máximo de erros admissível no processo de atualização dos dados de um datasetcliente. Isto é, ao resolver o processo e atualização, o servidor de dados tentará atualizar os dados noservidor SQL e, caso o número dos erros encontrados for maior do que o valor indicado no parâmetroMaxErrors, todo o processo será cancelado até que as correções sejam feitas. O processo de correçãodos erros encontrados é conhecido com Reconciliação. Se a MaxErrors for atribuído 0, todos ospossíveis erros serão retornados; do contrário, se seu valor for –1, nenhum error será retornado.

Veja um exemplo usando ApplyUpdates:

ClienteDataset1.ApplyUpdates(0); //Quaisquer erros serão retornadosClienteDataset2.ApplyUpdates(-1);//Nenhum erro é retornadoClienteDataset3.ApplyUpdates(5); //No máximo 5 erros serão tolerados.

Nota: o provider não pode detectar um conflito em atualizações em campos tipo Memo (texto commuitas linhas), e, portanto, não retornará erros nestes casos.

Indexando colunas com TClientDatasetDG 24-6..8O uso de índices provê muitos benefícios para suas aplicações. Os datasets clientes oferecem grandesuporte ao trabalho com índices de diversas maneiras. Se o dataset cliente é usado em uma aplicaçãodistribuída, ele herda os índices do servidor de dados, e exibe os dados ordenados por este índice. Oíndice padrão é denominado DEFAULT_ORDER.Você também pode usar outro índices existentes, assim como criar seus próprios índices.

Page 192: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

192

Adicionando um novo índice

Para criar um novo índice em um dataset cliente, chame o método AddIndex que permite-lheespecificar as propriedades do índice, tais como:

• O nome do índice.• Os campos marcados pelo índice.• A forma como o índice ordena os registros. Por padrão, ele o faz de forma ascendente e case-

sensitive.

Os índices que você cria são listados em ordem alfabética ascendente em seu computador. Aordenação em índices de campos string é case sensitive, mas você pode alterar este padrãoadiconando a opção ixCaseInsensitive nas opções de configurações dos índices.

De forma pouco comum nos datsets, os datasets clientes oferecem suporte a índices em camposcalculados e agregados. Estes índices trabalham de maneira idêntica a um índice normal de um campofísico.

Veja um exemplo simples, que ilustra algumas técnicas de trabalho com índices em datasets clientes:

procedure TForm1.QuickIndexClick(Sender: TObject);begin if Edit1.Text <> '' and ClientDataSet1.Fields.FindField(Edit1.Text) then begin ClientDataSet1.AddIndex(Edit1.Text + 'Index', Edit1.Text,[ixCaseInsensitive],'','',0); ClientDataSet1.IndexName := Edit1.Text + 'Index'; end;end;

No exemplo acima, se existir um campo com o nome digitado em um Tedit (edit1), um índice com onome do campo concatenado com a constante ‘Index” é criado. Em seguida, o dataset clienteClientDataset1 começa a usar o novo índice.

Excluindo e alternando índices

Você pode remover um índice de um dataset cliente usando o método DeleteIndex, que exige comoparâmetro o nome do índice a ser excluído. Você não pode excluir o índice atribuído comoDEFAULT_ORDER. A propriedade IndexName indica o nome do índice que um dataset cliente deveusar. Para trocar o índice a ser usado, basta atribuir o nome de um índice já existente à propriedadeIndexName dos datasets clientes. Veja um exemplo:

ClientDataset1.IndexName := ‘NovoIndice’;ClientDataset1.DeleteIndex(‘IndiceAntigo’);

Campos calculados e agregados

Como com qualquer dataset, você pode usar campos calaculados em um dataset cliente. Camposcalculados não são armazenados na estrutura de sua tabela, mas unicamente exibem valores

Page 193: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

193

calculados a partir de outros dados disponíveis. Datasets clientes, contudo, permitem uma grandeotimização no cálculo de campos calculados através do uso de campos internamente calculados.

Campos internamente calculados

Em outros datasets, sua aplicação deve computar os valores de campos calculados todas as vezes queocorrem uma alteração no registro ou o usuário edita qualquer campo no registro atual. O cálculo éfeito através do manipulador de eventos OnCalcField dos datasets.

Enquanto você continua podendo fazer isto, os datasets clientes permite-lhe minimizar o número devezes que os campos calculados são computados salvando seus valores em suas propriedades Data. Ocálculo de campos calculados continua sendo necessário quando você edita um registro, mas não seránecessário o recalculo todas as vezes que o registro se modificar. Para usufruir destes benefícios, vocêprecisa usar campos calculados internamente, em vez dos tradicionais campos calculados.

Campos calculados internamente, exatamente como os outros campos calculados, são calculados emum manipulador de eventos OnCalcField. Contudo, você otimiza seu manipulador checando apropriedade State dos datasets clientes. Quando a propriedade State contiver o valor dsInternalCalc,você necessita recalcular o valor do campo. De outra forma, se State contiver o valor dsCalcFields, seránecessário recalcular apenas os campos calculados comuns.

Em tempo de projeto, você define um campo calculado internamente adicionando um novo campo dotipo InternalCalc na janela NewField.

Usando campos agregados

Datasets clientes oferecem suporte a campos que sumarizam dados em grupos de registros. Na suaforma mais simples, campos agregados permitem-lhe obter informações tais como a soma dos valoresde uma coluna de um dataset cliente. Contudo, estes campos são flexíveis suficiente para suportar umagrande variedade de cálculos de sumarização para obter subtotais de grupos de registros definidos porum índice que suporta agrupamento.

FiguraA janela “New Field” é acessada quandovocê for criar um campo do tipoInternalCalc.

Page 194: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

194

Para especificar que você deseja criar sumarizações em um dataset cliente, use a propriedadeAggregates. Esta propriedade é uma coleção de especificações de sumarizações (TAggregate). Paracada item criado n propriedade Aggregates, a propriedade Expression o cálculo a ser efetuado atravésde expressões de cálculo simples, como

Sum(Field)

Ou mais complexas, como em

Sum(Qty * Price) – Sum(AmountPaid)

A tabela abaixo indica os operadores de sumarização aceitos:

Operador UsoSum Totaliza os valoes de camposnuméricos ou expressões.Avg Computa o valor médio para campos numéricos, de datas ou expressões.Count Especifica o número de valores não nulos para um campo ou expressãoMin Indica um valor mínimo para campos numéricos, string, datas ou expressões.Max Indica um valor máximo para campos numéricos, string, datas ou expressões.

Muitos tipos de campos agregados precisam de um índice específico para executar os cálculos desumarização. Tipicamente, isto é necessário em cálculos sobre grupos de dados. Neste caso, você devecriar um índice que suporte agrupamento de dados e, em seguida, indicar o seu nome na propriedadeIndexName da definição criada na propriedade Aggregates.

Copiando dados de outros datasets

Datasets clientes oferecem suporte para cópia dos dados de outro dataset. Este processo pode ser feitode maneira muito simples, tanto em tempo de projeto como em execução. Datasets clientes copiamestes dados sempre da mesma maneira, independentemente do tipo de dataset que servirá como fontede dados.

Assinalando dados diretamente

Você pode usar a propriedade Data de um dataset cliente para assinalar dados de um dataset paraoutro. Como a propriedade Data é do tipo OleVariant na forma de um pacote de dados, umdeterminado pacote de dados pode vir de outro dataset cliente ou de outros datasets através de umprovider. Desde que os dados estejam atribuídos à propriedade Data, o seu conteúdo é exibidoautomaticamente.Se o seu dataset cliente não usa um provider, você pode copiar os dados de outro dataset cliente comose segue:

ClientDataset1.Data := ClientDataset2.Data;

Page 195: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

195

Quando você copia a propriedade Data de outro dataset cliente, é gerada uma cópia do log dealterações também, mas a cópia não reflete quaisquer filtros aplicados. Para obter também este últimobenefício, é necessário clonar um cursor de dados.

Se você está copiando dados de outro dataset que não seja um dataset cliente, é possível criar umcomponente provider, ligá-lo ao dataset que servirá de fonte dos dados e copiar os dados:

TempProvider := TDatasetProvider.Create(Form1);TempProvider.Dataset := SourceDataset;ClientDataset1.Data := TempProvider.Data;TempProvider.Free;

Nota: quando a propriedade Data é assinalada diretamente, o novo pacote de dados não éadicionando ao pacote existente. Ao contrário, o novo pacote substitui completamente o pacoteanterior.

Clonando um cursor de dados

Datasets clientes fornecem o método CloneCursor para possibilitar o trabalho com uma outra visão deum dataset cliente específico durante a execução de um aplicativo. CloneCursor permite a um segundodataset cliente compartilhar os dados originais de outro dataset cliente. Devido ao fato de os dadosclonados serem compartilhados, o segundo dataset não pode alterar seus dados sem afetar o datasetoriginal.

O método CloneCursor requer três parâmetros. Source especifica o dataset cliente que deve serclonado. Resep e KeepSettings indicam se a cópia incluirá outras informações além dos dados.Propriedades como

• Filter, Filtered, FilterOptions, e OnFilterRecord• IndexName• MasterSource e MasterFields• ReadOnly• RemoteServer e ProviderName

são afetadas por estes dois últimos parâmetros. Para uma referência completa, consulte a ajuda doDelphi.

Manipulando TClientDataset com um provedor de dados

No contexto de aplicações distribuídas, o dataset cliente obtem os dados de um provider residente noaplicativo servidor de dados. Os providers são componentes que se encarregam do empacotamento dosdados obtidos de um dataset ou arquivo XML, enviando-os em seguida a um dataset cliente. Osproviders podem estar na mesma aplicação que um dataset cliente, mas é mais comum inserí-lo emoutra aplicação a fim de criar mecanismos remotos de comunicação entre aplicativos.

Após editar localmente os dados empacotados por um provider, um dataset cliente aplica todas asatualizações ao servidor remoto através do aplicativo servidor de dados. Os seguintes passos descrevemcomo usar um dataset cliente com um provider:

Page 196: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

196

• Especificação de um provedor de dados (provider);• Opcionalmente, obtenção de parâmetros da aplicação servidora de dados ou enviando parâmetros

para a mesma.• Opcionalmente, sobrescrição do dataset na aplicação servidora de dados.• Requisição dos dados da aplicação servidora.• Manipulação das constrições recebidas no servidor remoto e da aplicação servidora.• Gravação das alteraçõesdos dados.• Atualização dos registros.

Adicionalmente, datasets clientes também permitem a comunicação com um provider usando eventoscustomizados. O capítulo seguinte descreve em detalhes o funcionamento de providers nos ambientesDelphi e Kylix.

Especificando um provedor de dados (data provider )

Antes que um dataset cliente possa receber dados e aplicar atualizações em um servidor de dados, eedeve ser associado com um provedor de dados. Para associar um dataset cliente com um provedor emuma aplicação de arquitetura distribuída, use as propriedades RemoteServer e ProviderName dodataset cliente. Em aplicações de apenas uma camada e em aplicaçÕes que usam o modelo prota-arquivos, estas duas propriedades não são usadas. Ao usar um dataset cliente com um provider que éinstanciado em uma mesma aplicação, você não precisa usar a propriedade RemoteServer, mas aindapode usar a propriedade ProviderName.

A propriedade RemoteServer especifica o nome de um componente de conexão a partir do qual sepoderá obter uma lista de providers exportados. O componente de conexão reside no mesmo módulode aplicação que o dataset cliente, estabelecendo e mantendo uma conexão com uma aplicaçãoservidora, que às vezes é denominada “data broker”.Em tempo de projeto, após você especificar um valor para RemoteServer, é possível selecionar umprovedor da lista exibida na propriedade ProviderName. Esta lista também incluirá quaisquerprovedores locais que estiverem definidos na sua aplicação.

Obtendo parâmetros da aplicação servidora

Existem duas situações nas quais uma aplicação cliente precisa obter valores de parâmetros de umaaplicação servidora de dados:

• O cliente precisa saber o valor de um parâmetro de saída em um procedimento armazenado;• O cliente quer inicializar os parâmetros de entrada de uma consulta ou procedimento armazenado

para os valores correntes de uma consulta ou procedimento armazenado na aplicação servidora dedados.

Todo dataset que suporta parâmetros armazena os valores de parâmetros em sua propriedade Params.Estes valores são atualizados com qualquer parâmetro de saída se o dataset cliente recebe dados deuma aplicação servidora.Para maiores informações sobre o suporte a parâmetros em datasets clientes, consulte a ajuda on-linedo Delphi.

Page 197: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

197

Pasando parâmetros para a aplicação servidora

Os datasets clientes podem passar parâmetros para a aplicação servidora para especificar quais dadoseles querem obter. Estes parâmetros podem especificar.

• Valores de parâmetros para uma consulta ou procedimento armazenado da aplicação servidora;• Valores de campos que limitam os registros enviados nos pacotes de dados.

Você pode especificar valores de parâmetros que o se dataset cliente envia para a aplicação servidoraem tempo de projeto ou em execução. Em tempo de projeto, acesse a propriedade Params e forneçaos valores desejados. Em execução, use o método CreateParams da propriedade Params para adicionarum parâmetros em um dataset cliente. Este método retorna um objeto de parâmetros, e você podeespecificar seu nome, valor, tipo etc. Veja o exemplo abaixo:

with ClientDataset1.Params.CreateParams(ftInteger, ‘CustNo’’, ptInput) do AsInteger := 605;

Enviando consultas ou parâmteros de procedimentos armazenados

Quando um provider de uma aplicação servidora representa o resultado de uma consulta ouprocedimento armazenado, você pode usar a propriedade Params para especificar os valores dosparâmetros. Quando o dataset cliente requisitar os valores do provider ou executar seu método Execute(para executar uma consulta que não retorna dados), ele passa estes valores de parâmetros junto coma requisição de dados. Quando o provider recebe estes valores de parâmetros, ele os assinala para oseus dataset associado. A aplicação servidora executa o dataset e, se houverem dado retornados,retorna-os para o dataset cliente.

Limitando registros com parâmetros

Quando o provider na aplicação servidora representa os dados de um dataset baseado em tabela, vocêpode usar a propriedade Params para limitar os registros que são providos na propriedade Data. Cadanome de parâmetro deve corresponder ao nome de um campo no dataset baseado em tabela.

Por exemplo, considere uma aplicação cliente eu exibe as compras de um único cliente de cada vez.Quando o usuário identifica o cliente, o dataset cliente configura sua propriedade Params para incluirum parâmetro denominado ‘CodCli’, que representa o campo que armazena o código do cliente.Quando o dataset cliente requisitar os dados da aplicação servidora, ele passará o valor desteparâmetro. A aplicação servidora retornará, então, somente os dados deste cliente procurado.Esta técnica é mais eficiente do que permitir que o servidor recupere muitos dados e, após enviá-los aodataset cliente, este último se encarrecaria de filtrá-los para a exibição do dado procurado.

Sobrescrevendo o resultset de um provedor de dados

Page 198: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

198

Usualmente, os providers de uma aplicação servidora são associados com datasets que determina osdados que serão retornados à aplicação cliente. Estes datasets contêm uma instrução SQL ou fazemreferêncai a lgum objeto específico do banco de dados.

Se um provider permitir, um dataset cliente pode sobrescrever a propriedade que indica quais dadosele representa. Você faz isto através da propriedade CommandText de um dataset cliente.CommandText deve conter uma instrução SQL que irá substituir aquela usada pelo dataset associadoao provider, ou conterá o nome de uma tabela ou procedimento aramazenado que substituirá o nomede uma tablea ou procedimento armazenado do dataset associado ao provider. Este recurso permiteaos datasets clientes especificar dinamicamente os dados com os quais vai trabalhar.

Por padrão, o provider não permite que o dataset cliente faça esta troca. Para permitir o uso desterecurso, você deve adicionar o item poAllowCommandText na propriedade Options do provider daaplicação servidora. Do contrário, a ionstrução contida em CommandText será ignorada.

Os datasets clientes enviam sua instrução definida na propriedade CommandText de duas maneiras:

• Quando um dataset cliente é aberto;• Quando um dataset cliente envia um comando a ser executado na aplicação servidora. Ele o faz

através do método Execute.

Requisitando dados de uma aplicação servidora

A tabela seguinte lista as propriedades e métodos dos datasets clientes que determinam como osdados são transferidos para a aplicação cliente nas aplicações multi-camadas:

Propriedade ou método PropósitoFetchOnDemand Esta propriedade determina se um dataset cliente automaticamente transfere ou não os dados quando

for necessário.PacketRecords Esta propriedade especifica o tipo ou némero de registros a serem retornados em cada pacote de

dados.GetNextPacket Este método transfere o próximo pacote de dados da aplicação servidora.FetchBlobs Este método transfere qualqier campos BLOB para o registro atual quando a aplicação servidora não

os transfere automaticamente.FetchDetails Este método transfere datasets embutidos para cada registro quando a aplicação servidora não os

transfere automaticamente.

Por padrão, um dataset cliente recupera todos os registros de uma aplicação servidora. Você podecontrolar coo os dados são recuperados usando a propriedade PacketRecords e o métodoFetchOnDemand.

PacketRecords especifica tanto a quantidade de registros a recuperar em cada pacote de dados como otipo de registros a serem recuperados. Por padrão, PacketRecords é configurada para –1, o quesiginifica que todos os registros serão recuperados em um único pacote. Neste caso, o dataset clientenão precisa mais transferir dados, pois todos já estão disponíveis. Para sobrescrever este padrão,configure PacketRecords para um determinado número de registros. Por exemplo, o fragmento decódigo abaixo instrui um dataset client a recuperar pacotes com 10 registros cada:

ClientDataset1.PacketRecords := 10;

Este processo de recuperação de registros em diversos pacotes é conhecido como “incrementalfetching”. Os datasets usam este recurso auando o valor de PacketRecord é maior do que zero.

Page 199: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

199

O método GetNextPacket retorna um número de registros em um pacote. Este número é determinadopela propriedade PacketRecords. Se o número de registros recuperados é igual ao valor dePacketRecords, o dataset cliente sabe que existem mais pacotes disponíveis. Se GetNextPacket retorna0, então não existem mais pacotes a serem transferidos.

Nota: o recurso “incremental fetching” apenas funcionará desta forma se a aplicação servidora forcapaz de preservar informações de estado. Servidores COM que são sem estado ou que sãoexecutados em protocolos sem estado por natureza, como HTTP, não podem trabalhar com esterecurso através de seus métodos padrões. Nos capítulos posteriores, veremos como usar“incremental fetching” em servidores ou protocolos sem estado.

Manipulando constrições

Datasets clientes suportam dois tipos de recursos de manipulação de constrições:

• Constrições que são enviadas do aplicativo servidor nos pacotes de dados;• Constrições personalizadas escritas na aplicação cliente.

Este tópico abordará como os datasets clientes trabalham com recursos de constrições de dados.

Manipulando constrições do servidor de dados

Por padrão, constrições do servidor são expressões passadas para os datasets clientes pela aplicaçãoservidora, onde elas podem ser impostas na edição de dados dos usuários. Quando as constrições estãoagindo, o usuário pode editar dados nas aplicações clientes que violariam as constrições impostas naaplicação servidora. As constrições importadas de um aplicativo servidor para um cliente agem nosentido de impedir que os possíveis erros de edição dos dados sejam levados ao aplicativo servidor,sendo, de outra forma, detectados e tratados na própria aplicação cliente. Esta estratégia visa aminimizar a quantidade de erros durante o processo de atualização dos dados de um dataset cliente.

Enquanto a importação das constrições definidas no aplicativo servidor por um cliente é um recursoextremamente valoroso, pois possibilita ao programador preservar a integridade dos dados nasaplicações, podem existir situações onde será necessário desabilitar as constrições temporariamente.Por exemplo: se uma constrição de um servidor é baseada no máximo valor corrente de um campo,mas os datasets clientes usam o recurso de incremental fetching, o máximo valor corrente de umcampo pode diferir do valor máximo no servidor de banco de dados. Em uma outra situação, se umaaplicação cliente aplia um filtro sobre os registros quando as constriçõesestão ativadas, o filtro podeinterferir de uma maneira não prevista nas condições de constrições. Em cada um destes casos, aaplicações poderia desabilitar a checagem das constrições.

Para desabilitar a checagem de constrições temporariamente, chame o método DisableConstraints deum dataset cliente. Para retornar com a checagem de constrições, chame o método EnableConstraints.

Sempre chame estes dois métodos em um mesmo bloco de código, a fim de garantir que as checagensde constrições desativadas serão novamente colocadas em serviço. Veja um exemplo:

Page 200: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

200

Procedure Tform1.ProcessaPagamentos;BeginTryClientDataset1.DisableConstraints;

//Opera sobre os dados...

FinallyClientDataset1.EnableConstraints;End;End;

Nota: os métodos DisableConstraints e EnableConstraints determinam se um dataset cliente deveaplicar constrições aos seus dados. Contudo, eles não têm efeito algum quando a aplicaçãoservidora inclui informações de constrição nos pacotes de dados. Você pode previnir o envio deinformações de constriçÕes pelo servidor usando a propriedade Contraints do provider associado aum dataset cliente.

Adicionando constrições personalizadas

Você pode usar as propriedades dos campos (objetos fields) de um dataset cliente para criar condiçõesde constrições personalisadas. Cada componente field possui duas propriedades que você pode usarpara fazer isto:

• A propriedade DefaultExpression define um valor padrão que é assinalado ao campo caso o usuárionão informe um valor. Observe que se as constrições importadas do aplicativo servidor tambémdefine um valor para esta propriedade, o valor definido manualmente por você terá precedência.

• A propriedade CustomConstraints permite criar uma consdição de constrição que deve ser validadaantes de um valor para o campo ser aceito. As constrições definidas desta maneira são aplicadasadicionalmente a qualquer contrição importada do aplicativo servidor.

Adicionalmente, você também pode criar constrições executadas a nível de regsitro, isto é, quando umregistro tentar ser salvo. Isto é feito através da propriedade Constraints do dataset cliente.

No geral, você sempre deve definir suas constrições na aplicação servidora, a fim de que ela possatransmití-las aos clientes. Isto é feito assim em obediência à arquitetura de aplicações distribuídas, quesempre coloca as tarefas de validações a cargo da aplicação servidora. Existem ainda muitas outrasvantagens obtidas com o uso desta estratégia, mas algumas validações podem ser mais adequadas nacamada cliente.

Atualizando registros em um servidor

O processo de atualizaçãode registros em aplicações distribuídas é muito diferente do processo normalque conhecemos em aplicações Desktop ou Client/Server. Uma das diferenças maiores consiste naforma como os datasets clientes armazenam as alterações feitas, bem como a estratégia usada por umprovider para salvar os dados em um servidor SQL remoto.

Page 201: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

201

Este tópico irá abordar, em detalhes, todo o processo dee atualização de registros que deve sermplementado nas aplicações distribuídas.

Gravando as alterações

Quando uma aplicação cliente é conectada com um servidor de dados, os datasets clientes trabalhamcom uma cópia local dos dados passados pela aplicação servidora. O conteúdo das alterações égravado em um log de mudanças, que é a propriedade Delta dos datasets clientes. Para tornar asmudanças registradas em Delta permanentes, o dataset cliente precisa gravá-las no banco de dados.

Sempre que um dataset cliente envia suas alterações ao aplicativo servidor, os seguintes processoocorrem:

• A aplicação cliente chama o método ApplyUpdates de um objeto dataset cliente. Este método passao conteúdo da propriedade Delta do dataset cliente para a aplicação servidora.

• O componente provider da aplicação servidora aplica as atualizações no servidor de banco dedados, guardando quaisquer problemas que ele não consiga resolver ao nível de aplicaçõesservidoras.

• O componente provider da aplicação serviora retorna todos os registros não atualizados (quecontêm algum tipo de erro) para a aplicação cliente em um pacote de dados Result. Este pacotecontém as informações dos erros encontrados em cada registro.

• A aplicação cliente tenta reconciliar os erros retornados no pacote Result.

Reconciliando erros de alterações

Já vimos anterirormente como o método ApplyUpdates trabalha, e a função especial do seu parâmetroMaxErrors. Este tópico avançará nestes pontos, explicando em que consiste o processo de reconciliaçãodos dados retornados à aplicação cliente com o pacote Result.

Atualizações em uma só tabela

Usando datasets clientes em aplicações distribuída, a reconciliação dos dados junto ao aplicativoservidor pode ser tão simples como:

ClientDataset1.ApplyUpdates(-1);

Todas as ayualizações são feitas no contexto de uma transação do servidor SQL, e o exemplo acimopoderia ser traduzido da seguinte forma: “Atualize, em uma transação, todos os dados possíveis”.Porém, um apanhado maiss seguro exigiria mais rigor durante as atualizações. Como em:

ClientDataset1.ApplyUpdates(0);

Page 202: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

202

Já o código acima significa: “Dentro de uma transação, atualize tudo ou nada”. O que quer dizer que,se durante o processo de atualizações um erro for encontrado, o aplicativo cliente que enviou o pacotede atualizações deve resolver de alguma forma os dados “problemáticos”. O aplicativo poderásolucionar o problema através do processo de reconciliação dos dados, que consiste, basicamente, naapresentação dos erros ao aplicativo cliente em uma caixa de diálogo para que ele possa corrigir o erroou indicar o que fazer com aquela alteração.

Você pode usar a caixa de diálogo padrão para reconciliaçã de erros para oferecer um meio para queseu aplicativo possa executar estas tarefas. No Delphi 6, você introduz uma janela de reconciliaçãoacessando o Object Repository e, na página “Dialogs”, escolher o ícone “Reconcile Error Dialog”. Desdeque este formulário esteja disponível em sua aplicação, basta implementar o seguinte código nomanipulador de eventos OnReconcileError de seus datasets clientes.

Action:=HandleReconcileError(Dataset, UpdateKind, E);

Isto será suficiente para você oferecer um suporte completo para reconciliação de erros em seusaplicativos distribuídos. É claro que você não precisa obrigatoriamente usar esta janela padrão. Vocêpode criar qualquer uma que lhe agrade mais ou, se os aplicativos clientes de seu servidor são serviçosWEB de qualquer natureza, você poderá oferecer o suporte a reconciliação através de uma páginaHTML. Tudo feito com a mesma estratégia.

Atualizações em dados com joins

O processo de atualizações de dados em um dataset cliente que possua dados recuperados de junções(joins) de duas ou mais tabelas também é bastante simples. Geralmente, você faz joins para exibirdeterminadas relações entre as tabelas. Muitas vezes, as junções permitem-nos exibir dados de duas(ou mais) tabelas como se estivessem em apenas uma.

O controle do modo como uma atualização é feita, nestes casos, é determinado por um componenteespecífico para atualizações (um update dataset), que conterá em suas propriedades quais camposdevem ser atualizados. Estes componentes estão ligados a um dataset específico da aplicaçãoservidora, e o provider irá “consultá-lo” na hora de definir como gravar um registro.

Como cada dataset de um aplicativo servidor possui um componente a ele vinculado que irádeterminar como será feita a alteração ( em termos de SQL, quais os comandos serão usados), osproviders não precisam se encomodar em tentar descobrir como fazê-lo. Você sempre deveria colocarum componente dataset update para gerenciar as atualizações de seus datasets, pois isto garante umcontrole absoluto sobre todo o processo de atualização.

TClientDataset com dados baseados em arquivos

Os datasets clientes podem funcionar independentemente de um provider, tal como em aplicações debancos de dados baeadas em arquivos. Quando não existe um provider, contudo, datasets clientes nãopodem recuperar os dados de um servidor SQL remoto. Assim, o dataset cliente deve fazerindependentemente:

• Definir e criar tabelas;• Carregar e salvar dados dos arquivos;

Page 203: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

203

• Armazenar as edições no seus dados;• Salvar os dados.

O que é o modelo porta-arquivos? (briefcase )

O modelo porta-arquivos implementa uma arquitetura de acesso isolado a dados locais com suporte aatualizações locais e em servidores de dados. Uma aplicativo porta-arquivos possui um banco de dadosbaseado em arquivos, e é tipicamente um aplicativo muito leve. Os datasets clientes são o centro destaarquitetura, e implementam toda a funcionalidade de um banco de dados sem exigir quaisquer outrosmecanismos de acessos adicionais.

Embora os dados de um aplicativo possam ser usados como um banco de dados definitivo, você podepensar em um aplicativo porta-arquivos como um repositório de dados temporário; isto é, novos dadosadicionados em um aplicativo porta-arquivos um dia serão repassados a um banco de dados central.Por exemplo, imagine que você tenha uma empresa que venda planos de manutenção deequipamentos pesados. Você possui muitos vendedores de planos, e deseja automatizar todo oprocesso de vendas e andamento dos contratos de manutenção. A solução porta-arquivos é ideal pararesolver as suas necessidades.

Como os vendedores precisam realizar visitas aos seus cliente para fechar novos contratos e relizaruma série de outras tarefa referentes ao contrato do cliente visitado, um aplicativo porta-arquivos étudo o que eles precisam. Com um desses aplicativos instalados em um notebook, eles realizam novasvendas e muito mais. Após o retorno de um vendedor, basta atualizar o banco de dados central com asnovas informações trazidas pelo vendedor.

Como você já estudou, os datasets clientes oferecem grande suporte ao processo de atualização dosdados de maneira automática.

Este tópico introduzirá o uso de datasets clientes em aplicativos tipo porta-arquivos.

Carregando dados de um arquivo ou stream

Para carregar os dados de um arquivo, use o método LoadFromFile de um dataset cliente. Este métodoreque um parâmetro, que é o nome do arquivo que deve ser aberto. Este nome deve ser um caminhocompleto onde se encontra o arquivo, tal como “c:\Databases\Flat\Customer.cds’. Se você sempre usa omesmo arquivo com um dataset cliente, é possível usar a propriedade FileName para designar oarquivo.

Para carregar dados de um stream, use o método LoadFromStream do dataset cliente. Este métodorequer um parâmetro, que é uma referência a um objeto stream que fornecerá os dados.

Quando você usa LoadFromFile ou LoadFromStream, todos os dados são transferidos para apropriedade Data do dataset cliente. As alterações que você fizer nos dados são armazenadas napropriedade Delta, e não afetam os dados originais em Data. Para tornar uma alteração permanente,chame o método MergeChangeLog, que escreve todas as alterações na propriedade Delta. ApósMergeChangeLog ter sido chamado, a propriedade Data conterá um misto de dados existentes em Datacom as mudanças que podem ser feitas. Finalmente, a propriedade Delta é limpa.

Salvando dados em um arquivo ou stream

Page 204: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

204

Quando você chama o método MergeChangeLog, os dados que você possui estão salvos apenas emmemória. É necessário, em um determinado momento, escrever as alterações em um arquivo no disco.Esta operação pode ser feita usando o método SaveToFile.SaveToFile requer um parâmetro, que é o nome do arquivo onde eos dados serão escritos. Se oarquivo já existe, seu conteúdo será sobrescrito pelo atual do dataset cliente.

Você pode também salvar dados em um stream através do método SaveToSTream. Este método requerum parâmetro que é uma referência ao objet stream onde os dados serão armazenados.

Se você salvar os dados em um arquivo sem haver chamado antes o método MergeChangeLog e, emseguida, encerrar sua aplicação, não perderá as alterações feitas. Na próxima vez que executar suaaplicação todas as alterações estarão ainda disponíveis no log. Isto é importante para dar suporte aaplicações porta-arquivos.

Nota: SaveToFile não preserva qualquer índice criado dinamicamente em sua aplicação.

Outros datasets clientes

Com o Delphi 6, a arquitetura de datasets clientes foi expandida de forma a oferecer componentes quesimplificam ainda mais a criação de aplicações distribuídas. Estes componentes podem resumir oprocesso de trabalho entre um dataset cliente e um provider em um único componente.Grande parte do trabalho de configuração e conexão entre as peças de uma aplicação distribuídapodem ser isolados com o uso destes componentes.

TBDEClientDataset

De fato, TBDEClientDatase é um dataset cliente que possui um comonente provider (TDatasetProvider)interno para recuperar os dados de um dataset BDE. Você só pode usar TBDEClientDataset se a fontede dados deste dataset cliente for um dataset que trabalha com a BDE.

TBDEClientDataSet trabalha como um TClientDataset quando está conectado com um componenteTQuery local via um provider. Ele oferece algumas das propriedades e eventos dos componentesTQuery e TdatasetProvider, de form que você pode especificar a fonte DBE de onde os dados serãorecuperados e realizar muitas outras tarefas que não estariam disponíveis diretamente para umcomponente TClientDataset.

Adiconalmente, TBDEClientDataSet oferece as seguintes vantagens:

• Você pode usar TBDEClientDataSet para trabalhar com dados armazenados em arquivos oufornececidos por um servidor de banco de dados. Isto permite a implantação de aplicativos porta-arquivos com grande facilidade.

• Você pode obter vantagens de todos recursos únicos implementados em TClientDataset.

TIBClientDataset

TIBClientDataSet trabalha com armazenamento de dados local fornecidos por um dataset InterbaseExpress. Este componente é um dataset cliente que usa componentes TIBDataset e TdatasetProvider

Page 205: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

205

para transferir e aplicar atualizações de dados. A grande vantagem do componente TIBClientDataset éo fato de permitir o o acessos a datasets Interbase Express sem a necessidade de um componenteprovedor externo. Além disto, TIBClientDataSet agirá como um dataset cliente comum, excetuando-seo fato de acessar exclusivamente fontes de dados através da Interbase Express.

O uso de atualizações em cache local permite muitas vantagens, como:

• Você pode usar o componente TIBClientDataSet para trabalhar com dados armazenados emarquivos em disco, assim como em um servidor de banco de dados Interbase/Firebird. Estacaracterística permite uma fácil implementação de uma aplicação porta-arquivos. Todos osrecursos e vantagens oferecidas pelo componente TClientDataset estão igualmente disponíveis paraTIBClientDataSet.

• Sua aplicação pode ser convertida muito mais facilmente para um outro mecanismo de acesso adados, uma vez que existem grande similaridades de arquitetura entre todos os datasets clientes;os componentes TIBClientDataSet, TSQLClientDataSet e TBDEClientDataSet podem ser usadossempre da mesma maneira, apesar de acessarem fontes de dados através de mecaninsmosdiferentes.

TIBClientDataSet trabalha como TClientDataset quando está conectado a um componente TIBDatasetatravés de um provider, exceto pelo fato de tanto este dataset como o provider são alocadosinternamente. Contudo, TIBClientDataSet é inteligente o suiciente para expor diversas propriedades,eventos métodos destes componentes internos, de forma a oferecer-lhe grande controle sobre eles.Paralelamente ao acesso a dados via um dataset TIBDataset, TIBClientDataSet pode também acessardados armazenados em arquivos no disco de maneira idêntica à que você pode fazer com umcomponente TClientDataset.

TSQLClientDataset

O componente TSQLClientDataSet é um dataset cliente que usa os componentes TSQLDataset eTdatasetProvider para transferir dadose aplicar atualizações. TSQLClientDataSet combina o mais rápidoacesso e a mais fácil distribuição de um dataset unidirecional com a abilidade de edição e navegaçãode dados de um dataset cliente.

Devido ao fato de TSQLClientDataSet possuir um componente TSQLDataset interno, TSQLClientDataSetusa a DBExpress como mecanismo de acesso a dados. Mas, TSQLClientDataSet trabalha como umdataset cliente, o que significa que ele recupera os dados de um provedor e aplica as atualizaçÕes damaneira comum a todo dataset cliente. Assim, TSQLClientDataSet trabalha como o componenteTClientDataset quando está conectado a um TSQLDataset local através de um provedor, excetuando-seo fato de o dataset e o provider que usa são internos. Da mesma forma que outros datasets clientes,TSQLClientDataSet oferece mecanismos para você controlar as propriedades, eventos e métodos destesdois componentes internos.

Adicionalmente, você pode usar TSQLClientDataSet para acessar e escrever dados em arquivosarmazenados em disco. Isto permite o uso de TSQLClientDataSet para o desenvolvimento de aplicativosporta-arquivos que manipulam dados de bancos baseados em arquivos.

Nota: TSQLClientDataSet não é recomendado para uso em relacionamentos tipo mestre/detalhe.Ele não pode otimizar as consultas que usa para este propósito, o que resulta em um desempenhomuito baixo.

Page 206: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

206

CC AA PP ÍÍ TT UU LL OO 11 77 –– UU SS AA NN DD OO PP RR OO VV EE DD OO RR EE SS DD EE DD AA DD OO SS

Os componentes provedores (TdataSetProvider e TXMLTransformProvider) oferecem o mecanismo maiscomum pelo qual datasets clientes podem obter seus dados. Os componentes provedores:

• Recebem a requisição de dados de um dataset client (ou um XML broker), transferindo os dadosrequisitados em um pacote de dados transferível, e retornando os dados para um dataset cliente(ou XML broker). Esta atividade é denominada “provimento” (“providing”).

• Recebem atualizações de dados de um dataset client (ou XML broker); aplicam as atualizações aum servidor de banco de dados, dataset fonte, ou um documento XML, e registram quaisqueratualizações que não podem ser aplicadas, retornando-as a um dataset cliente para oprocessamento de uma reconciliação. Esta atividade é denominada “resolução” (“resolving”).

Muito do trabalho de um componente provedor acontece automaticamente. Você não precisa escreverqualquer código no provedro para criar pacotes de dados a partir de dados obtidos em datasets oudocumentos XML, bem como para aplicar atualizações. Contudo, os componentes provedores incluemum número de eventos e propriedades que permitem um controle mais direto de sua aplicação sobreas informações que são empacotadas e enviadas em resposta às requisições dos clientes.

Quando usar TBDEClientDataSet,TSQLClientDataSet, ou TIBClientDataSet, um provedor é encapsuladointernamente, e aplicação não possui acesso direto a este componente interno. Quando se usaTClientDataset ou TXMLBroker, contudo, o provedro é um componente separado que você pode usarpara controlar quais informações são empacotadas para os clientes, assim como definir as operaçõesde resposta nos eventos que podem ocorrer durante o processo de provimento e resolução. OsDataSets clientes que têm provedores internos oferecem uma interface para algumas propriedades eeventos do provedor interno, mas quando for necessário um controle maior, você pode desejar usarum componente TClientDataset com um provedor separado. Na situação onde se usa um componenteprovedor separado, ele pode residir na mesma aplicação que um dataset cliente (ou XML broker), oupode residir em uma aplicação servidora que é parte de um sistema distribuído.

Este capítulo descreve como usar um componente provedor para controlar a interação com datasetsclientes ou XML brokers.

Page 207: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

207

Determinando a fonte dos dados

Quando você usa um componente provedor, é necessário especificar a fonte que ele usa para obterdados que serão empacotados. Dependendo da sua versão do Delphi, você pode especificar esta fonteatravés de um dos seguintes componentes:

• Se for prover os dados a partir de um dataset, use o componente TdataSetProvider.

• Se for prover dados de um documento XML, use o componente TXMLTransformProvider.

Usando um dataset como fonte de dados

Se o provedor é um TdataSetProvider, configure a sua propriedade DataSet para indicar o componentedataset que será a fonte dos dados. Em tempo de projeto, selecione o dataset de uma lista disponívelna propriedade dataset. TdataSetProvider interage com dataset fonte usando a interfaceIproviderSupport. Esta interface é introduzida para acesso a todos descendentes de TDataset, de formaque qualquer espécie de datasets estarão disponíveis. Contudo os métodos implementados emIproviderSupport não são mais que stubs que não fazem nada ou geram exceções. As classes dedatasets providas com Delphi (Datasets baseados em BDE, ADO, dbExpress, e InterBase Express)sobrescrevem estes métodos para implementar a interface IproviderSupport em uma maneira maisusual. Datasets clientes não adicionam nada na implementação do IproviderSupport herdado, maispodem ainda ser usados como um dataset fonte, desde que a propriedade ResolveToDataSet docomponente provedor esteja configurada como true.

Usando um documento XML como fonte de dados

Se o componente provedor é um provedor XML, configure a propriedade XMLDataFile do provedor paraindicar o documento que servirá de fonte. Provedores XML devem tranformar o documento fonte dedados em pacotes de dados, de forma que você também deve especificar como transformar aqueledocumento em um pacote. Esta transformação é manipulada pela propriedade TransformRead docomponente provedor. TransformRead representa um objeto TXMLTransform. Você pode configurar assuas propriedades para expecificar que transformações fazer, e usar os seus eventos para prover umesquema personalizado de transformação.

Comunicando-se com um dataset cliente

Toda a comunicação entre um provedor e um dataset cliente ou XML broker toma lugar através dainterface IAppServer. Se o provedor esta na mesma aplicação que o cliente, esta interface éimplementada por um objeto escondido gerado automaticamente para você, ou por um componenteTLocalConnection. Se o provedor é parte de uma aplicação distribuída, esta é a interface do módulo dedados remoto da aplicação servidora. Muitas aplicações não usam IAppServer diretamente, masinvocam-na indiretamente através das propriedades e métodos dos datasetes clientes ou XML borker.No entanto, quando for necessário, você pode fazer chamadas diretas para a interface IAppServerusando a propriedade AppServer de um dataset cliente.

A tabela abaixo lista os métodos da interface IAppServer, assim como os métodos e eventoscorrespondentes do componente, assim como os correspondentes métodos e eventos dos compoentesProvider e datasets clientes. Estes métodos IAppServer incluem um parâmetro denominado Provider.

Page 208: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

208

Em aplicações multi-camadas, este parâmetro indica o provedor na aplicação servidora com o qual odataset cliente se comunica. Muitos métodos também incluem um parâmetro do tipo OleVariantchamado OwnerData, que permite a passagem de inormações customizadas entre um dataset cliente eum provedor. OwnerData não é usada comumente, mas é passada em todos os manipuladores deeventos de forma que você pode descrever código que permite ao seu provedor ajustar-se àsinformações personalizadas antes e após cada chamada de um dataset cliente.

Como aplicar atualizações com um TDatasetProvider

O componente TXMLTransformProvider sempre aplica atualizações em um documento XML a eleassociado. Ao usar um componente TdataSetProvider, contudo, você pode escolher como asatualizações são feitas. Por padrão, quando o componente TdataSetProvider aplica atualizações eresolve os possíveis erros encontrados elel se comunica diretamente com o servidor de banco de dadosusando intruções SQL geradas dinamicamente. Este apanhado tem a vantagem de que a aplicaçãoservidora não realiza atualizações duas vezes (primeiro para o dataset e, então, para o servidorremoto).

Contudo, nem sempe você pode desejar este apanhado. Por exemplo, você pode querer usar algunsdos eventos no componente dataset. Alternativamente, o datasete que você usa pode não suportar ouso de intruções SQL (como quando se provê dados de um TClientDataset). O componenteTdataSetProvider permite que você decida quando aplicar atualizações a um servidor de banco dedados usando SQL, ou o datasete fonte ao configurar a propriedade ResolveToDataSet. Quando estapropriedade for true, as atualizações são aplicadas para o dataset; do contrário, serão aplicadasdiretamente no servidor de banco de dados.

Controlando as informações em um pacote de dados

Quando você trabalhar com um dataset provier, existem algumas maneiras de controlar qualisinformações são incluídas nos pacotes de dados a serem enviados para e do cliente:

• Especificando quais campos aparecem nos pacotes de dados;

• Configurando opções que influenciam os pacotes de dados;

• Adicionando informações personalizadas aos pacotes de dados.

Nota Estas técnicas de controle do conteúdo de pacotes de dados estão disponíveis apenas paradataset provider. Ao Usar TXMLTransformProvider, você pode apenas controlar o conteúdo depacotes de dados através de um arquivo de transformação usado pelo provedor.

Especificando os campos que serão inclusos

Ao usar um dataset provider, você pode controlar quais campos são incluídos no pacote de dados aocriar campos persistentes nos datasets que o provedor usa para contruir o pacote de dados. Então, oprovedor inclui apenas estes campos. Campos cujos valores são gerados dinamicamente pelo dataset

Page 209: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

209

fonte (tais como campos calculados ou do tipo lookup) podem ser incluídos, mas aparecem nosdatasets clientes como campos estáticos e não alteráveis.

Opções que influenciam os pacotes de dados

A propriedade Options do dataset provider permite especificar se campos BLOB ou tabelas de detalhe(nested tables) são enviados, assim como se as configurações das propriedades dos componentes fieldsdo dataset fonte também devem ser transferidas no pacote de dados, que tipo de atualizações sãopermitidas e muitas outras opções. A tabela seguinte lista os valores que podem ser incluídos napropriedade Option.

Valor SignificadopoAutoRefresh O provider atualiza o dataset cliente toda vez que ele grava seus dadospoFetchBlobsOnDemand Campos BLOB não são incluído no pacote de dados.poFetchDetailOnDemand Quando o provedor representa o mestre em uma ligação mestre/detalhe, os possíveis dados do

dataset de detalhe não são incluídos.poIncFieldProps O pacote de dados inclui propriedades (sempre que aplicável) dos campos do dataset, tais como:

Alignement, DisplayLabel, Visible, DisplayFormat, EditFormat, MaxValue etcpoCascadeDeletes Se o provider representa o mestre de uma ligação mestre/detalhe, automaticamente deleta os

dados de detalhe quando um registro for deletado.poCascadeUpdates Se o provider representa o mestre de uma ligação mestre/detalhe, automaticamente atualiza os

dados de detalhe quando um registro for alterado.poReadOnly Indica que o dataset cliente não pode aplicar atualizações no provider.PoDisableEdits O dataset cliente não pode alterar registros existentes.PoDisableInserts O dataset cliente não pode inserir novos registros.PoPropagateChanges As mudanças feitas pelo Servidor SQL como parte de um processo de alteração são enviadas junto

com o pacote de dados.PoAllowCommandText Indica que o dataset cliente pode enviar comandos SQL para o provider.

Informações personalizadas em pacotes

Dataset Providers podem adcionar informações definidas pelas aplicações aos pacotes de dados atravésdo evento OnGetDataSetProperties. Esta informação é codificada como um tipo OleVariant, earmazenada sob o um nome que você especifica. Datasets clientes podem, então, recupera ainformação usando o método GetOptionalParam. Você pode também especificar qual a informação éincluída no pacote Delta que o dataset cliente envia quando atualiza registros. Neste caso, o datasetcliente nunca pode conhecer da informação, mas o provedor pode enviar uma mensagem para simesmo.Ao adicionar informações customizadas no evento OnGetDataSetProperties, cada atributo individual (àsvezes chamado “parâmetro adicional”) é especiifcado usando um array de dados do tipo Variant quecontém três elementos: o nome (uma string), o valor (um Variant) e um flag boolean que indica se ainformação deveria ser incluída no pacote Delta quando for ser aplicada um atualização. Adicionemúltiplos atributos para criar um array Variant de outros arrays Variant. Por exemplo, o seguintemanipulador de eventos OnGetDataSetProperties envia dois valores, a hora e a data e o número totalde registros no dataset fonte. Apenas a hora e a data é retornada quando o dataset cliente aplica asatualizações:

procedure TMyDataModule1.Provider1GetDataSetProperties(Sender: TObject;DataSet: TDataset; out Properties: OleVariant);beginProperties := VarArrayCreate([0,1], varVariant);

Page 210: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

210

Properties[0] := VarArrayOf(['TimeProvided', Now, True]);Properties[1] := VarArrayOf(['TableSize', DataSet.RecordCount, False]);end;

Quando o dataset cliente aplica as atualizações, a hora na qual os registros foram providos pode serlida através do evento OnUpdateData do provedor:

procedure TMyDataModule1.Provider1UpdateData(Sender: TObject; DataSet:TCustomClientDataSet);varWhenProvided: TDateTime;beginWhenProvided := DataSet.GetOptionalParam('TimeProvided');...end;

Respondendo a requisições de datasets clientes

Em muitas aplicações multi-camadas, as requisições de dados feitas pelos clientes são satisfeitas deforma completamente automática. Um dataset cliente requer um pacote de dados chamando o métodoGetRecords (indiretamente, através da interface IappServer). Automaticamente, o provedor responde àrequisição, gera o pacote de dados e o envia para o dataset cliente. O provider pode editar os dadosapós eles terem sido “empacotados”, mas sempre antes de enviá-los para os clientes. Por exemplo, oprovider poderia querer encriptar dados sensíveis antes de enviálos etc.

Para editar o pacote de dados antes de enviá-lo aos clientes, escreva um manipulador de eventosOnGetData.

Respondendo a atualizações de datasets clientes

Um provedor aplica atualizações a um banco de dados baseado no pacote de dados Delta, que elerecebe um um dataset cliente. Como com todo método chamado a partir da interface IappServer, oprovider tem a oportunidade de comunicar informações de persistência de dados e estado com ocliente antes de atualizar os dados. Esta comunicação é feita usando os manipuladores de enventoBeforeApplyUpdates e AfterApplyUpdates. Estas comunicações são feitas por motivos muito variados. Omais importante deles, contudo, é aplicar constrições e verificar a integridade dos dados obtidos docliente. Esta seção abordará algumas tÉcnicas de constrição de dados e manipulação de error oferecidas pela arquitetura de acessodistribuída presente no Delphi.

Resolvendo erros de atualizações no provider

Uma primeira informação que o desenvolvedor sempre deve Ter em mente é que o aplicativo servidorsempre deve manipular as constrições e erros que não exigem interação humana para seremdetectadas ou manipuladas. Além deste nível, você poderá implementar constrições de erros tanto noaplicativo cliente (usando os datasets clientes) quanto no aplicativo servidor (usando providers).

Page 211: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

211

Se uma condição de erro é detectada quando o provider tenta atualizar um registro do pacote Delta,um evento OnUpdateError ocorre. Se a aplicação servidora não pode resolver por si mesma o erro, elaguarda temporariamente uma cópia do registro que gerou o erro até que o processamento daatualização tenha terminado. Então, o provider retorna ao cliente para que ele possa (através deinteração humana) resolver as atualizações inconstritas. Este mecanismo é denominado de“Reconciliação de Erros” e permite que você exiba uma janela (também uma página html ou outromecanismo) que exibirá a mensagem de erro gerada pelo Servidor SQL ou pelo aplicativo servidor,bem como o conjunto dos dados não constritos. Além disto, o usuário é informado em que condição aexceção foi gerada (ao inserir, editar ou deletar dados) e um conjunto de opções possíveis para que oproblema possa ser solucionado.Este recurso permite que o usuário possa alterar a condição que gerou a exceção e novamente enviaro pacote corrigido ao provider.

Respondendo a eventos gerados nos clientes

Os componentes provider implementam um evento de propósito geral que permite ao programadorcriar suas próprias chamadas, diretamente, aos providers. O evento OnDataRequest lida com dadosOleVariant, o que permite uma interface suficientemente genérica para acomodar quaisquer tipos dedados e parâmentos que você precise usar para comunicar-se com um provider.

Para gera um evento OnDataRequest, a aplicação cliente chama o método DataRequest de um datasetcliente.

Page 212: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

212

CC AA PP ÍÍ TT UU LL OO 11 88 -- TT RR AA BB AA LL HH AA NN DD OO CC OO MM OO CC OO MM PP OO NN EE NN TT EE TT FF II EE LL DD

Associadamente aos datasets, o Delphi nos oferece uma grande quantidade de componentes que lidamcom os campos de dados (colunas) de uma tabela ou consulta. Tais componentes são denominadosfields (campos) e descendem da classe básica Tfield. Descendentes de Tfield representam colunasindividuais em um datasets. Você nunca usa um componente Tfield diretamente em suas aplicações.Por padrão quando você coloca um dataset em sua aplicação e o abre, o Delphi automaticamenteassinala um descendente de Tfield específico de um tipo de dado para representar cada coluna natabela do banco de dados. Em tempo de projeto, você pode sobrescrever campos criadosdinamicamente ao invocar o editor de campos para criar campos perssistentes que substituem oscriados de forma automática.

Este capítulo descreve as propriedades, eventos e métodos comuns para os objetos Tfield e seusdescendentes.

Page 213: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

213

A arquitetura dos componentes fields

Como todos os componentes Delphi de acesso a dados, componentes field não são visuais. Estescomponentes também não são diretamente visiveis em tempo de projetos; ao contrário, eles sãoassociados com componete dataset e possibilitam o acesso de controles ligados a banco de dados aoscampos de um dataset. Falando de forma geral um componente Tfield espécifico representa ascaracterísticas de uma única coluna em um dataset, assim como os seu tipo de dado de tamanho. Eletambém representa as características de exibição de um campo, tais como alinhamento, formato eformato de edição. Finalmente, como você rola de registro em registro em um dataset, umcomponente field também abilita a visualização e a mudança do valor para aquela coluna no registrocorrente. Por exemplo, um componente TFloatField tem quatro propriedades que afetam diretamente aaparência dos seus dados:

• Alignment• DisplayWidth• DisplayFormat• EditFormat.

A VCL e a CLX oferecem muitos descendentes de TField especializados na manipulação de um tipoespecífico de dado. A tabela abaixo informa os componentes fields mais comuns que você sempreusará em suas aplicações.

Componente DescriçãoTADTField um campo ADT (Abstract Data Type)TAggregateField um campo agregado em um Dataset ClientTArrayField um campo arrayTAutoIncField aceita números inteiros entre a faixa de -2 147 483 648 para 2 147 483 647.usado para campos Paradox cujos

valores são automaticamente incrementadosTBCDField aceita números reais com um número de decimais fixo, até 18 dígitos, a faixa depende do número de decimaisTFMTCBCDField Representa um campo BCD (binary-code decimal)TBooleanField aceita valores true ou falseTBlobField aceita dados binários, o limite teórico máximo é 2 GBTBytesField aceita dados binários, o limite teórico máximo é 2 GBTCurrencyField aceita números reais entre a faixa de 5.0 * 10 -324 a 1.7 * 10308. Usado em campos Paradox com dois digitos

decimais de precisãoTDatasetField aponta para um outro objeto DatasetTDateField aceita valores de datasTDateTimeField Aceita valores de data e hora ao mesmo tempoTfloatField aceita números reais entre a faixa de 5.0 * 10 -324 a 1.7 * 10308.TBytesField Dados binários. Limite máximo de bytes: 255TIntegerField aceita números inteiros entre a faixa de -2 147 483 648 para 2 147 483 647.TLargeIntegerField aceita números inteiros entre a faixa de -263 a 263.TMemoField Aceita texto em muitas linhas. Limite teórico máximo: 2 GB.TNumericField Aceita números reais na faixa entre 3.4 * 10-4932 e 1.1 * 104932.TReferenceField Trabalha com um ponteiroa um objeto de banco de dado relacional.TSmallIntField Aceita números inteiros na faixa entre –32768 e 32768TStringField Dados string. Tamanho máximo em bytes: 8192.TTimeField Aceita valores de horas.TVarBytesField Dados binários. Tamanho máximo de bytes: 255.TWordField Aceita números entre a faixa de 0 e 65535.TIBStringField Dados string de servidor Interbase/Firebird. Pode exceder 8192 bytes.TGraphicField Trabalha com dados gráficos, como imagens.TInterfaceField Trabalha com ponteiros para interface IUnKnown de objetos COM.TDispatchField Trabalha com ponteiros para interface IDispatch de objetos COM.TIBBCDField Trabalha com números reais como valores monetários do Interbase.TCharField Trabalha com dados tipo CharTGUIDField Trabalha com GUID’s do Windows.TWideStringField Trabalha com widestrings.TVariantField Trabalha com dados variant.

Page 214: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

214

Criando um novo objeto TField

Objetos fields persistentes são cirados com o Fields editor, que prove uma maneira eficiente de se ler econfigurar as propriedades destes componentes. O uso de componentes fields persistentes garante quea cada vez que sua aplicação é executada ela sempre usa e exibe as mesmas colunas, na mesmaordem ainda que a estrutura física do banco de dados aos quais se referem tenha sido alterado. Assim,controles conscientes de dados (data-aware controls) podem trabalhar sempre da forma esperada. Seuma coluna na qual um field persistente é baseado é deletada ou modificada, o Delphi gera umaexcessão imediatamente antes de você ascesar esta coluna.

Para criar fields persistentes para um dataset é preciso :

• Coloque um dataset em um formulário ou módulo de dados;• Configure adequadamente as propriedades do dataset;• Dê um duplo clique no dataset para invocar o Fields editor;

Para inserir os objetos fields no editor acesse o menu de contexto do editor e escolha o item “AddFields”. Na lista de campos disponíveis que aparece então, selecione aqueles que deseja criar. Osfields inseridos são fields persistentes, isto é, objetos declarados e criados em tempo de projeto com osquais você pode trabalhar no Object Inspector como qualquer outro componentes.

Campos calculados

Um campo calculado exibe valores calculados em tempo de execução através de um manipulador deeventos OnCalcFields de um dataset. Por exemplo, você poderia criar um campo tipo string que exibevalores concatenados lidos de outros campos. Para criar um field calculado, acesse o menu de contextodo Fields Editor e escolha o item “New Field”. Na caixa de diálogo que aparece entre com o nome docampo a ser criado e escolha o tipo de dado que o campo calculado irá manipular. Observe que nemtodas as opções presentes nesta caixa de diálogo estarão disponíveis quando você determina um tipode dado em particular. Agora você precisa escrever algum código no manipulador de eventosOnCalcFields do dataset que contém o campo calculado. DNo fragmento de código que segue vocêverá um campo calculado que exibe a idade de um contato comercial a partir de um campo persistenteque contém a data de nascimento do contato:

procedure TDM.table1OnCalcFields (Sender: Tobject);beginTable1age.Value := Now - Table1Datanasc.Value;end;

Campos calculados devem sempre serem usados quando você deseja exibir algum dado que redundade calculos sobre outros dados fisicamente existentes nas tabelas de seu banco de dados.Se você está trabalhando com um dataset client, você pode também criar um campo calculadointernamente (InternalCalc Field). Você o cria exatamente da mesma forma que um campo calculadocomum. Para datasets clients a significativa diferença entre estes tipos de campos calculados é que osvalores calculados para um internalCalc field são armazenados como parte dos dados de um datasetclient.

Page 215: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

215

FiguraO editor de propriedadesFields Editor com um camposelecionado.

Campos Lookup

Um campo lookup é um objeto read-only, que exibe valores em tempo de execução baseados numcritério de pesquisa que você especifica . Na sua forma mais simples, um campo lookup passa o nomede um campo existente em uma pesquisa, e retorna um valor correspondente proveniente de outrocampo em um outro dataset. Por exemplo, considere um cadastro de endereços de clientes que possuaas tabelas “clientes” e “estados”. A primeira tabela armazena os dados dos clientes de sua empresa,como nome, endereço, cep, ect. A segunda tabela armazena os nomes de todos os estados dafederação. O campo “codUF” da tabela de clientes faz referência a um campo homônimo na tabela deestados. Um campo lookup pode exibir, dentro da tabela de clientes, o nome do estado a partir dosdados do campo codUF.Os campos lookup sãao definidos a partir da relação entre dois campos, e não exigem qualquercodificação para funcionarem de maneira adequada.

Campos Agregados

Um campo agregado exibe valores a partir de dados agregados em um dataset client. Dadosagregados são calculos que sumarizam os dados em um conjunto de registros. Para criar um campoagregado na caixa de diálogo “New Field”:

• Escolha um nome para o campo• Escolha um tipo de dado que o campo manipulará• Selecione a opção “Aggregate” para indicar que deseja criar um campo agregado

Coloque a expressão de calculo para o campo agregado criado em sua propriedade ExprText. Desde deque um TAggregateField persistente seja criado, um controle ligado a dados pode exibir normalmenteos seus valores.

Configurando propriedades de TField

Você pode configurar o conjunto de propriedades e eventos existentes para os componentes Fieldspersistentes em tempo de projeto. As propriedades destes componentes controlam a forma como um

campo é exibido em um controle, por exemplo em um TDBgrid, ou se seus valores podem ser

Page 216: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

216

alterados. Os eventos de objetos fields controlam a forma como os dados são tranferidos, alterados ouvalidados.Para editar as propriedades de um objeto TField, selecione-o no Fields Editor e acesse o ObjectInspector.O Fields Editor é um editor de propriedades de objetos muito simples. Consiste, basicamente, de umjanela constendo a lista de componentes fields associados a um dataset. Ao selecionar um membrodesta lista, todos as suas propriedades e eventos podem ser acessadas. Para inserir novos componentesfields, use o menu de contexto do Fields Editor.

A tabela seguinte sumariza as propriedades de exibição que podem ser editadas:

Propriedade DescriçãoAlignment Especifica como o dado será alinhado em um contole: esquerda, centralizado ou direita.DiplayWidth Especifica o número de dígitos que serão exibidos.DisplayFormat Determina a formatação dos dados a serem exibidos.EditFormat Determina como exibir a formatação dos dados durante a sua edição.ConstraintErrorMessage Texto a ser exibido quando houver uma violação de uma constrição.Currency Se for deninido como True, formata o campo com formato de valores monetários.DisplayLabel Determina o nome da coluna em um controle TDBGrid.EditMask Cria uma máscara que formatará a entrada de dados em um controle.FieldKind Especifica o tipo do field.FieldName Especifica o nome da coluna na tabela ao qual o field se refere.HasConstraints Indica se existem constrições aplicadas ao field.ImportedConstraints Especifica uma cosntrição importada de um servidor SQL.Index Especifica a ordem do field no dataset.LookupDataset Especifica o dataset a ser usado pelo field como fonte de dados lookup.LookupKeyFields Especifica o field do dataset a ser usado como fonte pesquisa de um field lookup.LookupResultField Especifica o field do dataset a ser usado como dados exibido de um field lookup.MaxValue Determina o valor máximo a ser aceito em fields numéricos.MinValue Determina o valor mínimo a ser aceito em fields numéricos.Name Indica o nome do componente fieldOrigin Especifica o nome do campo como ele aparece no banco de dados.Precision Especifica o número de dígitos significativos em campos numéricos.ReadOnly Indica se os dados do field poderão ser alterados ou não.Size Especifica o número máximo de caracteres que podem ser exibidos ou editados.Visible Determina se o field será visível em um controle TDBGrid ou não.

Note que nem todas estas propriedades estão disponíveis para todos os componentes fields. Porexemplo, um componente TStringField não tem as propriedades Currency,MaxValue, ou Displayformat,e um componente TFloatField não tem a propriedade Size. Enquanto o propósito de muitaspropriedades se encerra em si mesmas, outras propriedades, tais como Calculated, requeremprogramação adicional para se tornarem usuais. Outras, tais como DisplayFormat, EditFormat, eEditMask, são interrelacionadas; suas configurações devem ser coordenadas.

Conjuntos de atributos e máscaras

A propriedade EditMask provê uma maneira de controlar o tipo e a faixa de valores que um usuáriopode entrar em um controle associado com os componentes TStringField,TDateField, TTimeField, eTDateTimeField. Você pode usar máscaras existentes, ou então criar as suas próprias máscaras. Amaneira mais fácil pra executar estas tarefas é através do Input Mask editor. É possível, contudo, editarmanualmente uma máscara na propriedade EditMask de um Tfield. Este editor permite criar e editarum formato de máscara. Você pode textar este novo formato a fim de verificar se trabalha na formadesejada.

Page 217: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

217

O Delphi também provê rotinas de formatação inteligentes chamadas automaticamente para oscomponentes TFloatField, TCurrencyField, TIntegerField, TSmalllnField, TWordField, TDateField,TDateTimeField e TTimeField. Para usar estas rotinas você não precisa fazer nada. A tabela abaixomostra as funcionalidades destas rotinas.

Rotina Usada por...FormatFloat TFloatField, TCurrencyFieldFormatDateTimer TDateField, TTimeField, TDateTimeFieldFormatCurr TCurrencyField

Apenas propriedades de formatação apropriadas para o tipo de dado de um componente Field estãodisponíveis para um dado componente. As convenções de formatação para datas, horas, moedas evalores numéricos são baseadas nas propriedades de configurações regionais no Painel de controle dossistemas operacionais Windows. Por exemplo, usando as configurações padrão para o Brasil, umacoluna TFloatField com a propriedade Currency configurada para True, configura a propriedadeDisplayFormat para o valor 1234,56 para R$ 1234,56, enquanto a propriedade EditFormat é 1234,56.Em tempo de projeto ou execução, você pode editar as propriedades DisplayFormat e EditFormat deum componente Field afim de sobrescrever as configurações de exibição padrão para este campo. Damesma forma, é possível escrever manipuladores de eventos OnGetText e OnSetText para executarformatações customizadas pra um componente field.

Manipulando eventos

Como muitos componentes, os descendentes de TField possuem manipuladores de eventos a elesassociados. Ao escrever um desses manipuladores, você pode controlar eventos que afetam a entradade dados nos fields ligado a um controle. A tabela seguinte lista os eventos dos componentes fields.

Evento DescriçãoOnChange Disparado quando o valor do componente field muda.OnGetText Disparado quando do componente field é retornado ou editado.OnSetText Disparado quando o valor do componente field é atribuído.OnValidate Disparado quando o valor do componente field é mudado e precisa sofrer validações.

Os eventos OnGetText e OnSetText são primariamente usuais para programadores que querem realizarformatações customizadas que vão além daquelas fornecidas automaticamente pelos componentesfields. O evento OnChange é usual para para possibilitar a execução de tarefas específicas junto acontroles ligados a dados, tais como os processos de abilitação e desabilitação de controles e menus de

FiguraO editor de máscaraspara objetos fiels.

Page 218: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

218

navegação de dados. O evento OnValidate é útil quando se quer controlar a validação da entrada dedados em sua aplicação antes de se retornar os valores para um servidor de banco de dados.

Métodos de componentes fields

Os métodos dos componentes fields disponíveis em tempo de execução permitem-lhe converter valoresde um tipo de dado para outro, enviar o foco para um determinado controle etc.O controle de foco dos controles associados a componentes fields é importante quando sua aplicaçãoexecuta uma validaçao orientada a registro em um evento de datasets, tais como OnBeforePost. Avalidação pode ser executada em um componente field independentemente do controle a ele associadopossuir o foco de entrada. Neste tipo de validação, a idéia básica é a de que quando a validação dosdados de um field falhar, o foco de entrada seja direcionado para o controle associado ao field paraque o usuário possa entrar com as correções. Isto é feito através do método FocusControl doscomponentes field. Este método transfere o foco de entrada para o primeiro controle no formulário queestiver associado ao componente field. Um manipulador de eventos deveria chamar um métodoFocusControl de um campo antes da validação do compo. O fragmento de código abaixo ilustra comochamar FocusControl para o field company da tabela customers:

CustomersCompany.focusControl;

A tabela que segue lista alguns métodos de componentes field e seus usos. Para uma referênciacompleta de todos os métodos disponíveis em TField, consulte a ajuda do Delphi.

Método DescriçãoAssignValue Atribui um valor para um componente field usando rotinas automáticas de conversão.Clear Limpa o valor de um componente field, atribuindo-o o flag null.GetData Retorna dados não-formatados do field.IsValidChar Determina se um caracter digitado em um controle é permitido para o componente field.SetData Atribui dados não-formatados ao componente field.

Conversões de valores de campos

Funções de conversão trabalham convertendo dados de um tipo para outro tipo. Por exemplo, a funçãoAsString converte valores numéricos e Boolean para uma representação no formato string. Oscomponentes field possuem muitas funções de conversão, as quais terão grande utilidade nodesenvolvimento de suas aplicações. A tabela seguinte exibe as principais funções de conversão queestão disponíveis para diversos descendentes de TField.

AsVariant AsString AsInteger AsFloat AsCurrency AsDateTime AsBooleanTIntegerField ü ü ü ü TSmallintField ü ü ü ü TWordField ü ü ü ü TFloatField ü ü ü TCurrencyField ü ü ü TBCDField ü ü ü TDateTimeField ü ü ü ü TDateField ü ü ü ü TTimeField ü ü ü ü TBooleanField ü ü TBytesField ü ü

Page 219: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

219

TVarBytesField ü ü TBlobField ü ü TMemoField ü ü TgraphicField ü ü TStringField ü ü ü ü ü ü

Observe que o método AsVariant é recomendado para conversões entre todos os tipos de dados. Emalguns casos conversões nem sepre são possíveis. Por exemplo, AsDateTime pode ser usado paraconverter um formato string, date, time, ou datetime apenas se o valor em string for reconhecível parauma formatação datetime. Uma tentativa falha de conversão dispara uma exceção.

Em outros casos, a conversão é possível, mas os resultados da conversão não são sempre intuitivos.Por exemplo, o que significa converter um valor TDateTimeField em um formato Float? O métodoAsfloat converte a porção referente a data de um field para um número de dias a partir de 12/31/1899,e converte a porção referente a horas para uma fração de 24 horas. A tabela abaixo lista as conversõesque produzem resultados especiais.

Conversão ResultadoString para Boolean Converte ‘True’, ‘False’, ‘Yes’ e ‘No’ para boolean. Outros valores geram exceçõesFloat para Integer Arredonda valores decimais.DateTime para Float Converte a data para número de dias a partir de 12/31/1899 e a hora para uma fração de 24 horas.Boolean para string Converte qualquer valor boolean para ‘True’ ou ‘False’.

Em outros casos as conversões são de todo imposíveis. Nestes casos tentativas de conversão tambémdisparam exceções.

Você usa uma função de conversão como usaria qualquer método de um componente. As conversõessempre ocorrem antes de um assinalamento ser feito. Por exemplo, o fragmento seguinte converte ovalor de CustomersCustNo para uma string e assinala a string para a propriedade text de um controleTedit:

Edit1.Text := customerscustNo.AsString;

Acessando valores de campos

Existem muitas maneiras de você acessar programaticamente os valores de componentes fields. Osvalores são lidos sempre acessando a propriedade Value dos componentes field.Uma diferença de abordagem essencial é colocada quando acessamos componentes fields criadosdinamicamente ou, por outro lado, acessamos dados de componentes fields persistentes. Paracomponentes fields criados dinamicamente, o compilador não pode saber qual o descendente de tfielddeverá ser criado para representar uma determinada coluna. Então, também não poderá saber qual otipo de dado que este descendente manipula, e usará sempre o tipo de dado Variant na propriedadeValue do componente field. Como os componentes fields persistentes estão declarados em tempo deprojeto, o compilador sabe determinar quais características suportam e os tipos de dados que cada umdeles pode manipular. Conseqüentemente, uma referência ao valor de um field persistente se basearáno tipo de dado que este suporta.Por exemplo, os fragmentos de códigos que seguem ilustram as situações discutidas.

varI: integer;

Page 220: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

220

I := Tabela1.Fields.Fields[1].Value;

Neste caso, value é um variant que será atribuído a uma variável do tipo integer.

varI: integer;

I := CustNumber.Value;

Mas, agora, o compilador sabe que a propriedade value é do tipo inteiro, pois o código se refere a umcomponente field persistente (CustNumber) que manipula dados do tipo integer. Neste exemplo, ocomponente CustNumber é um TintegerField, o que determina o tipo de dado integer da suapropriedade Value.

Acessando valores de componentes field

Você pode acessar os valores de um componente field através do Dataset ao qual o componente fieldestá associado ou diretamente, caso o componente field seja persistente. A única forma de acessarcomponentes field dinamicamente criados é através de propriedades do Dataset a ele vinculado.

Todo dataset tem uma propriedade denominada Fields, que pode ser usada para acessar tantocomponentes fields persistentes como dinâmicos. Para usar a propriedade Fields, você deve saber aordem dos componentes fields de um dataset. Usa-se números ordinais para enumerar a ordem docomponente field, sempre iniciando-se com 0. Como discutido acima, os valores devem ser convertidospara um tipo de dado desejado, uma vez que a referência em tempo de projeto à propriedade value decomponentes fields dinâmicos sempre retorna um variant. Por exemplo, o fragmento que segue copia ovalor do primeiro field de um dataset para um controle TEdit, convertendo-o para o formato string.

Edit1.Text := Dataset1.Fields[0].AsString;

o que é idêntico a

Edit1.Text := Dataset1.Fields.Fields[0].AsString;

Outra maneira de acessar um componente field é através do nome da coluna da tabela do banco dedados que o componente representa. Este método é muito útil, mas você precisa conhecer o nome dacoluna para usá-lo. Os métodos de conversão também devem ser usados de maneira idêntica aomencionado acima. Veja um exemplo:

Edit1.Text := Dataset1.FieldByName(´CustNumber´).AsString;

Conferindo o valor corrente de um field

Se sua aplicação usa um dataset client ou administra um dataset que é a fonte para um componenteProvider em uma aplicação servidora, voc~e pode usar a propriedade CurValue para examinar o valorde um campo. A propriedade CurValue representa o valor atual de um componente field, incluindo asmudanças feitas por outros usuário do banco de dados. Tipicamente, um aplicação multi-camadas

Page 221: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

221

apresenta os valores atuais de campos quando você tenta atualizar dados de campos que já foramalterados após você recuperá-lo e editá-los.

Constrições de componentes fields

Constrições são regras que devem ser cumpridas para que valores de um banco de dados estejamíntegros, do ponto de vista das regras comerciais implementadas. O Delphi implementa diversos tiposde contrições em níveis diferentes, para cada uma das necessidades específicas de suas aplicações.Esta seção discute constrições implementadas em componentes fields.

Constrições de servidores SQL

Os componentes field podem usar constrições vindas de um servidor SQL remoto. Todas as constriçõessão regras ou condições que impõem um limite no escopo ou faixa de valores que um campo de umatabela pode armazenar. Muitos servidores de banco de dados SQL usam constrições para imporpossíveis valores aceitáveis em uma coluna. Poe exemplo, uma coluna em uma tabela pode nãopermitir valore nulos (NULL), podem requer que os dados sejam únicos em uma determinada colunaetc. Em vez de você reimplementar todas estas constrições em seus aplicativos clientes, o Delphioferece a propriedade ImportedConstraints para propagar as constrições de um servidor localmente.Estas constrições limitam os valores de entrada de alguma maneira, como em

x > 0 and X <100

Para adicionar constrições nos componentes fields, use a propriedade CustomConstraint, que sãoimplementadas adicionalmente às constrições importadas de um servidor SQL. Se as constrições de umservidor são modificadas, os valores da propriedade ImportedConstraint também são alterados, mas asconstrições personalizadas não sofrem qualquer alteração.

Constrições personalizadas

Adicionalmente a constrições de servidores SQL, suas aplicações podem criar e usar constriçõespersonalizadas que são locais a sua aplicação. Como tais, constrições personalizadas podem ser usuaisao oferecer uma pré-validação da entrada de dados, mas não podem ser aplicadas em dados recebidosou enviados para um servidor.Para criar constrições personalizadas, configure a propriedade CustomConstraint para especificar umacondição de constrição, e escreva uma mensagem de erro a ser exibida ao usuário quando houverviolação da constrição na propriedade ConstraintErroMessage. Constrições personalizadas também sãostrings SQL, tais como

X > 0 and x < 100

O nome usado para se referir ao valor do campo pode ser qualquer string que não seja uma palavrareservada da linguagem SQL. O nome usado para referir-se ao valor do campo pode ser qualqueristring que não é uma palavra reservada da SQL.

Page 222: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

222

Descendentes complexos de TField

Além dos componentes fields que manipulam tipos de dados simples (como um tipo inteiro ou string),existem descendentes que manipulam tipos de dados complexos , tais como arrays ou datasets. Estetópico introduzirá o uso dos descendentes conplexos de TField.

Usando campos de objetos

Os descendentes de TObjectField suportam tipos de campo ADT (AbstractDataType), array, Dataset ereference. Todos esses tipos contem referencias a campos filhos ou outros datasets.Fields ADT e reference são mapeados para campos que contem outros campos filhos, que eles mesmopodem ser de qualquer tipo escalar ou objeto. Um array field contem um array de campos filhos, todosdo mesmo tipo. Filds dataset e reference são mapeados para campos que acessam outros datasets, eum field reference armazena um ponteiro (reference) a outro objeto persistente. A tabla abaixo ofereceuma descrição simples de alguns fields complexos.

Componente DescriçãoTADTField Representa um campo ADT (Abstract Data Type).TArrayField Representa um campo array.TDatasetField Representa um campo que contém uma referência a um dataset “embutido”.TReferenceField Representa um campo REF, um ponterio para um ADT.

Quando você adiciona algum destes objetos a um dataset, campos de objetos persistente sãoadicionados altomaticamente para você, e à propriedade ObjectView do dataset é atribuido o valortrue. Isto instrui aos campos para serem armazenados hierarquicamente, em vez de isoladamente.

Trabalhando com fields ADT

ADTs são tipos definidos pelo usuário criados no servidor, e são similares a estruturas ( Structures). UmADT pode conter muitos tipos de campos escalares, array fields, referencefields e datasets. Existe umavariedade de mecanismos para acesssar os dados em fields ADT. Os seguintes exemplos assinala umvalor de um campo filho para um TEdit chamado CityEdit e usa a seguinte estrutura ADT:

Address Street City State zip

E os seguintes campos persistentes criados para o componente Ttable chamado Customer.

CustomerAddress: TADTField;CustomerAddrStreet: TStringField;CustomerAddrCity: TstringField;CustomerAddrState: TstringField;CustomerAddrZip: TStringField;

Page 223: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

223

A linha de código abaixo usa um field persistente e demonstra o método recomendado para acessardados em fields ATD.

CityEdit.Text := CustomerAddrCity.AsString;

Ou, de uma maneira um pouco diferente.

CityEdit.Text := Customer.FieldByName (´Address.City´).AsString;

Existem ainda outros mecanismos de acesso a dados em fields ADT como, por exemplo o uso dapropriedade fieldvalues.

Trabalhando com TArray Field

Um Tarrayfield consiste de um conjunto de fields do mesmo tipo. Os tipos podem ser escalares (comofloat ou string) ou não escalares (um ADT), mas TarrayField de arrays não é permitido. Existe umavariedade de maneiras de acessaros dados em um TarrayField, o seguinte exemplo preenche umTListBox com todos os elementos não nulos de um array:

varOrdeDates: TArrayField;I: Integer;

beginfor I:= 0 to OrderDates.Size - 1 do begin if OrderDates.Fields [I]. Isnull then Break; OrderDateListBox.Items.Add(OrderDates [I]); end;end;

Os exemplos seguintes assinalam um valor de um campo filho a um Tedit chamado TelEdit, e usam oarray TelNos_Array, que é o sexto elemento de um array de strings. Os seguntes fields persistentes,criados para o TTable Customer, são usados no exemplos

CustomerTelNos_Array: TArrayField;CustomerTelNos_Array0: TStringField;CustomerTelNos_Array1: TStringField;CustomerTelNos_Array2: TStringField;CustomerTelNos_Array3: TStringField;CustomerTelNos_Array4: TStringField;CustomerTelNos_Array5: TStringField;

Esta linha de código usa um field persistente e assinala o seu valor para o TEdit.

TelEdit.Text := CustomerTelNos_Array0.AsString;

Os fragmentos de código abaixo requerem que a propriedade ObjectView dos datasets tenham umvalor True. Você pode acessar o valor de campos filho através da propriedade FieldValues do dataset.FieldValues aceita e retorna um tipo variant, de maneira que ele possa manipular e converter camposde qualquer tipo. Por exemplo,

Page 224: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

224

TelEdit.Text :=TArrayField(Customer.FieldByName('TelNos_Array')).FieldValues[1];

Que é o mesmo que

TelEdit.Text := TArrayField(Customer.FieldByName('TelNos_Array'))[1];

Page 225: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

225

CC AA PP ÍÍ TT UU LL OO 11 99 -- CC RR II AA NN DD OO UU MM AA AA PP LL II CC AA ÇÇ ÃÃ OO DD EE SS KK TT OO PP

Uma aplicação desktop usa um banco de dados local para obter e armazenar informações. Existemmuitos bancos de dados locais disponíveis atualmente, como MS Acess e Paradox, e muitas aplicaçõessimples podem ser desenvolvidas satisfatoriamente sobre a base desktop. Uma característica dosbancos de dados locais é a sua velocidade, uma vez que todo o processo de acesso e transferência dedados é realizado em um único computador.

Com Delphi, você pode desenvolver aplicativos que acessam bancos de dados locais usando a BDE,ADOExpress ou datasets clientes. Usando datasets clientes, em muitos casos você desenvolverá umaplicativo multi-camadas, e não um desktop. Contudo, ainda assim é possível desenvolver desktops comdatasets clientes como TBDEClientDataset.

Para o desenvolvimento de desktops, a Borland recomenda o uso da BDE, que é um middleware quepossui muitos recursos avançados para o trabalho com bancos locais, e suporta uma grandequantidade de bancos sisponíveis hoje em dia. Contudo, existem casos onde a opção por ADO pode serconsiderada muito seriamente. O caso típico é se sua aplicação terá de acessar bancos de dados MSAcess. A tecnologia ADO oferece um grande suporte (nativo a nívem do sistema operacional) a estebanco de dados, e você conhecerá grandes recursos disponibilizados por provedores ADO para acessoa MS Acess. Por outro lado, a ADOExpress oferece um suporte completo ao desenvolvimento deaplicativos que usam ADO.

Por estas razões, usaremos ADOExpress acessando um banco MS Acess durante o desenvolvimento deum aplicativo de exemplo. Este capítulo ilustrará também as necessidades inerentes aodesenvolvimento de aplicativos desktop’s.

Page 226: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

226

Projeto de aplicação Desktop

Desenvolveremos agora um aplicativo desktop de exemplo, usando MS Acess como banco de dadoslocal. Durante este tópico você conhecerá diversos aspectos a serem considerados no início dodesenvolvimento de um aplicativo que acesse bancos de dados locais.

Bancos de dados locais

Bancos de dados locais são aqueles que não possuem um mecanismo de gerenciamento de acesso,transações e manutenção mais complexos, conhecidos como servidor de dados. Os servidores de dados(SGDB) são muito sofisticados e usam a linguagem SQL como mecanismo de acesso e manutenção dosdados. Você pode usar, limitadamente, a linguagem SQL para acessar bancos de dados locais, maseste trabalho sempre é feito por um middleware, como a BDE.

Uma característica fundamental para a compreensão de como funcionam os bancos de dados locais é amaneiro como os dados são armazenados e recuperados: bancos locais são orientados a registros etabelas. Uma tabela é um conjunto de colunas de tipos de dados específicos. Um registro é uma linhade uma tabela contendo as colunas a ela pertencentes.

Bancos locais trabalham com o gerenciamento de acesso de forma a proibir o acesso a registros quesão editados por um usuário. Este comportamento é denominado travamento “pessimista”. Embora, osdiversos bancos locais possam diferir quanto ao nível de travamento pessimista (travamento a nível debanco, tabela, coluna ou registro), não são capazes de oferecer um gerenciamento completo deacessos concorrentes de usuários. Esta característica é explicada pelo fato de os bancos locais teremsido desenvolvidos para acesso de apenas 1 usuário, sem quaquer concorrência aos dados. Recursoscomo transações, triggers etc não existem em bancos locais, mas você pode implementar umfuncionamento limitado de transações em alguns bancos gerenciados pela BDE ou ADO. Você podeconstruir aplicativos rápidos e eficientes acessando bancos de dados locais, como Paradox, MS Acess oudBase, mas terá muitos problemas se desejar oferecer suporte multi-usuário real, tanto quanto aoacesso a dados como no uso de seu aplicativo.

Apesar disto, um banco de dados local pode ser uma solução eficiente em muitos casos.

Usando ADOExpress como mecanismo de acesso

A BDE oferece um suporte completo ao trabalho com bancos de dados locais. O que mais diferencia aBDE da ADO, do ponto de vista da disponibilidade de acessos a bancos, é o fato de a BDE oferecer umsuporte completo a muitos bancos de dados, enquanto, por padrão, a ADO suporta um número menor.É claro que você pode instalar novos drivers OLEDB que permitirão um acesso a muitos outros bancos,mas estes drivers não estão automaticamente disponíveis como ocorre com a BDE.

A ADO, contudo, pode possuir vantagens atraentes sobre a BDE em determinados aspectos ecircunstâncias. Particularmente, se você vai desenvolver uma aplicação desktop que acessará MS Acess,considere seriamente o uso de tecnologia ADO em suas aplicação. ADOExpress oferece um mecanismorequintado de acesso a bancos de dados MS Acess através de um provedor OLEDB da Microsoft que éinstalado automaticamente com o sistema operacional Windows 98 ou superiores.

O melhor de tudo é que ADOExpress disponibiliza suporte ao desenvolvimento de bancos de dados damesma maneira a qual você está acostumado, usando a BDE. Como será demonstrado ao longo destecapítulo, você não necessitará reaprender nada sobre acesso a bancos de dados, principalmente devidoao fato de tantos os datasets ADOExpress como os BDE possuirem uma herança comum de TDataset.Você também deve considerar o fato de ADOExpress disponibilizar datasets muito semelhantes a

Page 227: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

227

TTable ou TQuery, com os quais você já se acostumou. Os componentes TADOTable e TADOQuerytrabalham de forma semelhantes aos semelhantes que usam BDE, o que facilitará ainda mais todo oexercício de aprendizagem.

Modelo de dados

Para o exemplo a ser desenvolvido, utilizaremos o banco Acompanhamento de projetos 2000.MDB, queé acessado através do arquivo com o mesmo nome. Por padrão, o endereço deste arquivo é o seguinte:

C:\Delphi Basico\Capitulo18\Acompanhamento de projetos 2000.mdb

Este é um banco MS Acess 2000, que objetiva guardar dados sobre o acompanhamento financeiro deprojetos de pesquisa e desenvolvimento de energias alternativas.

Na imagem que segue, você pode observar o modelo de relacionamento entre as entidades do banco.

Iniciando o desenvolvimento do aplicativo

Neste tópico serão vistos os primeiros passos no desenvolvimento do aplicativo, que consistem namontagem da unidade principal do projeto, e na estruturação de um módulo de dados para o projeto.

Criando um novo projeto

Você sempre começa o desenvolvimento de um aplicativo em Delphi da mesma maneira: criando umnovo projeto de desenvolvimento. No nosso exemplo, será o projeto de um aplicativo GUI comum, nãouma dll ou um aplicativo console. Como o Delphi 6 permite a criação de aplicativos Windows ou Linux,teremos, inicialmente, de decidir qual a biblioteca de componentes que iremos usar, a VCL e a CLX. Nonosso caso, a escolha é muito simples: só faz sentido criar um aplicativo Windows, pois bancos dedados MS Acess não existem no mundo Linux. O mesmo se pode dizer da tenologia ADO queusaremos.

Tendo sido decidido isto, basta acessar o menu “File | New | Application” para iniciar um aplicativo GUIdo Windows. Ao fazer isto, tudo o que você tem é um formulário com sua unidade de código e aunidade de projeto do aplicativo (você pode ver o seu conteúdo acessando “Project | View Source”)chamada “Project1”. Salve os dois clicando no botão “Save All”. O nome do executável do aplicativoserá o nome dado à unidade de projeto (.dpr).

Evindentemente você pode dar qualquer nome a estas unidades, mas nós chamaremos a unidadedeste primeiro formulário “Main.pas” e o projeto como “AcomProj.dpr”. A unidade Main.pas contém o

Modelo exemplo desktop.gif

Page 228: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

228

formulário criado, que é o principal da aplicação. Antes de mais nada, ajuste as propriedades desteformulário conforme se pode ver na tabela abaixo:

Propriedade Valor SignificadoName FrmMain Dá um nome ao objeto TForm que é a janela principal do aplicativo.Caption Acompanhamento de projetos Dá um título à janela principal do aplicativo.Position PoScreenCenter Determina que a janela aparecerá no centro da tela do computadorShowHint True Determina os hints dos controles dos aplicativos da janela serão exibidos.

A janela principal de um aplicativo GUI é aquela que, quando fechada, encerra a execução daaplicação. É nela que são inseridos a maioria dos controles gerais de acesso às funcionalidades dosaplicativos, tais como menus, barras de ferramentas, botões etc. Embora nem sempre seja assim,normalmente a janela principal do aplicativo é a primeira a ser criada na memória e a última a ser deledestruída. É na janela “Project Options” que você determina qual será a janela principal de suaaplicação; basta selecioná-la na lista das janelas disponíveis em seu aplicativo. Acesse a janela “ProjectOptions” através dos menus “Project | Options”. Na página “Application” desta janela, você podetambém digitar um título para sua aplicação, bem como escolher o ícone que ela usará. No Windows, otítulo de um aplicativo é aquele que aparece na barra de tarefas do Windows quando ele é executado.

Para o nosso exemplo, escolha um ícone que lhe agradar e escreva algum título sugestivo que seráexibido da barra de tarefas. Se você compilar e executar o aplicativo (F9), verá que já temos umprograma; ele não faz nada de útil, mas é um programa Widows.

Módulos de dados

Antes de prosseguirmos o trabalho com a janela principal, iremos voltar nossas atenções para um novoelemento que será adicionado no aplicativo: um módulo de dados. O que é um módulo de dados? Esteobjeto é um container para outros objetos não-visuais, e permite um acesso centralizado aoscomponentes e rotinas que manipulam os dados em uma aplicação que acessa banco de dados. Todoaplicativo que acessa bancos de dados deveria possuir ao menos 1 módulo de dados.

Figura –O ObjetoTdataModule.

Page 229: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

229

À primeira vista, um módulo de dados poderia parecer muito semelhante a um objeto TForm(formulário) comum de uma aplicação Windows. Contudo, em nada ele se assemelha a um formulário,a começar pelo fato de um formulário ser invisível durante a execução de um aplicativo, enquanto umformulário é, por excelência, um objeto visual. Módulos de dados não podem conter quaisquer tipos decomponentes visuais (controles) e são armazenados em memória de maneira especial. A IDE do Delphie Kylix oferecem um mecanismo visual para lidar com módulos de dados durante a fase de projeto;este mecanismo se assemelha a uma janela, mas não é um formulário.

Um módulo de dados guarda não somente datasets, mas componentes de conexão, timers (TTimer) equaisquer outros componentes não-visuais. No nosso exemplo, o módulo de dados servirá comocentralizador de objetos e rotinas de acesso e conexão a banco de dados. Existem muitos tipos demódulos de dados. Pelo momento, estudaremos m módulo de dados tradicional, um objeto da classeTDataModule. Você cria um módulo de dados para uma aplicação que usa a VCL através dos menus“File | New | Data Module”. Ao longo de muitos pontos de nosso aplicativo, referiremo-nos ao nossomódulo de dados; então, altere a sua propriedade Name para um nome simples e sugestivo, como“DM”. Salve a unidade do módulo de dados com o nome DataModule ou semelhante.

Trabalhando com um módulo de dados

Neste tópico aprenderemos como trabalhar com um módulo de dados e os componentes de acesso adados nele inseridos. Também veremos como configurar uma conexão com uma fonte de dados ADO,e os detalhes do trabalho com datasets e fields.

Conectando com o banco MS Acess

A primeira coisa que precisamos fazer para acessar os dados de nosso banco é fornecer um meio deconectar nosso aplicativo ao banco de dados. No desenvolvimento de aplicativos que usam bancos dedados, este raciocínio é uma necessidade sempre presente. Como usamos ADOExpress para acessar obanco de dados, esta tarefa deve ser executada pelo componente de conexão TADOConnection. Insiraum componente TADOConnection no módulo de dados DM. Ele pode ser acessado na página ADO daPalheta de Componentes. Altere a propriedade Name deste componente para “ADOCon”.

TADOConnection estabelece e mantém uma conexão com uma fonte de dados ADO através de umprovedor OLEDB. O provedor que usaremos é o Microsoft.Jet.OLEDB.4.0. Este provedor trabalha comfontes de dados MS Acess, e é instalado com o sistema operacional. Contudo, você pode trabalhar comqualquer outro provedor que saiba manipular uma banco MS Acess, sem que seja necessária qualqueralteração no comportamento do aplicativo ou seu código-fonte.

A maneira mais simples de se configurara TADOConnection é através da sua propriedadeConnectionString. Esta propiedade possibilida a criação de uma string de conexão de uma maneiramuito simples. Como você deve estar se lembrando, TADOCOnnection estabelece conexões com osprovedores OLEDB através de uma string de conexão parametrizada. Esta string contém todas asinformações necessárias para se fazer uma conexão com um provedor OLEDB. Embora você possadigitar esta string de conexão na propriedade ConnectionString, certamente será muito mais produtivoe seguro acessar a caixa de diálogo para criação destas strings de forma visual. Para isto, basta clicarno botão que aparece quando a propriedade ConnectionSTring recebe o foco no Object Inspector.Nesta caixa de diálogo, selecione a opção “Use connection string” e clique no botão “Build”. Agora vocêpode configurar a sua conexão para um provedor OLEDB. A tabela abaixo resume o significado e valordas propriedades que usaremos.

Page 230: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

230

• Na página “Provedores”, selecione Microsoft Jet OLEDB 4.0 (ou outro provedor que acesse bancosMS Acess);

• Na página “Conexão”, selecione ou digite o endereço (path) do nosso banco de dados.

• Clique no botão “Testar conexão” para verifcar se está tudo correto. Caso positivo, feche as duascaixas de diálogo para que a string de conexão seja criada.

Pelo momento, isto é suficiente para começarmos. Repare que a propriedade ConnectionString docomponente ADOCOn possui um valor criado pelos editores. Embora nós tenhamos inserido o caminho(path) do banco de dados de forma estática, futuramente teremos de possibilitar a customização destedado, uma vez que possivelmente este path não existirá quando o programa for instalado para osusuários. Isto será feito um pouco mais à frente.

Agora, para efeito de um teste final, altere as propriedades LoginPrompt e Connected de ADOConrespectivamente para False e True. LoginPrompt determina se uma caixa de diálogo de identificação deusuário (login) será automaticamente exibida. Como não usaremos senhas de usuários, o valor Falsegarante que esta caixa não será exibida. Já a propriedade Connected ativa a conexão de ADOCon coma fonte de dados que ele usa. A figura abaixo mostra o Object Inspector exibindo a string de conexãocriada.

Inserindo datasets para acesso aos dados

O próximo passo é inserir os datasets que serão vinculados às tabelas de nosso banco de dados. Namaioria dos casos, bancos de dados locais podem ser manipulados de forma muito eficiente comdatasets baseados em tabelas. Estes datasets são flexíveis e não exigem nenhum processo especialapara a edição, inserção ou deleção de dados.

Figura –O objetoTADOConnection jáconectado com o bancoMSAcess.

Page 231: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

231

Page 232: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

232

Page 233: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

233

CC AA PP ÍÍ TT UU LL OO 22 00 -- CC RR II AA NN DD OO AA PP LL II CC AA ÇÇ ÕÕ EE SS CC LL II EE NN TT // SS EE RR VV EE RR

Este capítulo enfoca o suporte ao desenvolvimento de aplicações cliente/eervidor em Delphi. Vocêconhecerá alguns dos conceitos mais importantes a serem observados surante o desenvolvimento deaplicações que usam este modelo de acesso. Por exemplo, conheceremos os fundamentos técnicos dodesenvolvimento cliente/servidor e o trabalho com bancos de dados relacionais e SGBD’s.

Page 234: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

234

Introdução ao modelo cliente/servidor

O termo cliente/servidor foi inicialmente aplicado para a arquitetura de software que descrevia oprocessamento entre dois programas. Nesse contexto, a aplicação cliente requisitava um serviço queera então executado pelo programa servidor. Entretanto, esse termo ainda não distinguia se oprograma cliente e o programa servidor estavam sendo executados em uma mesma máquina ou emmáquinas diferentes. Hoje, quando se fala em cliente/servidor, está se referindo a um processamentocooperativo distribuído, onde o relacionamento entre clientes e servidores são relacionamentos entrecomponentes tanto de software quanto de hardware. Portanto, estaremos interessados na arquiteturacliente/servidor envolvendo duas ou mais máquinas em um processo cooperativo para executar aaplicação.

Arquitetura cliente/servidor

Essa arquitetura também consiste de vários computadores, cada um com seu próprio processamento,interligados em rede. A diferença básica para a arquitetura Resource-Sharing é que aqui já começa ahaver um processamento distribuído cooperativo. Parte do processamento, que era feito pela máquinada aplicação, é feito agora pela própria máquina responsável pelo armazenamento e distribuição dainformação, diminuindo assim o tráfego de informações na rede. Portanto, pode-se e deve-seselecionar os dados que serão enviados para o usuário para uma melhor eficiência do ambiente.Esse modelo já começa a retirar partes específicas de processamento das aplicações que eramexecutadas pelas máquinas clientes, centralizando-as nas máquinas de localização física maisadequada, garantindo assim uma melhor distribuição do processamento e utilização do ambiente.Através dessas especializações garante-se também um melhor gerenciamento e facilidade demanutenção dos serviços devido a sua concentração em um ou poucos locais físicos.

Podemos citar alguns benefícios que esta nova arquitetura traz para o ambiente computacional dasempresas:

• Permite às corporações alavacarem a tecnologia de computadores “desktops”. Hoje, as estações detrabalho já possuem um poder computacional considerável, por um custo muito mais baixo, antessó disponível em “Mainframes”.

• Permite que o processamento seja feito mais próximo da origem dos dados reduzindo o tráfego narede.

• Facilita a utilização de aplicações gráficas e multimídias. Isto permite a construção de aplicaçõesque excedem as expectativas dos usuários proporcionando-lhes um real aumento de produtividade.

• Permite e encoraja a utilização de sistemas abertos, já que clientes e servidores podem rodar emdiferentes hardwares e softwares, livrando as corporações de arquiteturas proprietárias.

Entretanto, essa arquitetura ainda não é perfeita. Algumas características necessárias para umcompleto processo distribuído ainda não foram observadas nesse modelo que ainda apresenta algumasdeficiências:

• Se uma porção significante da lógica da aplicação for movida para o servidor, esse se torna um“gargalo” assim como na arquitetura de “Mainframe”. Para resolver esse problema seria necessário

Page 235: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

235

uma melhor distribuição e gerenciamento do processamento da lógica da aplicação. Isto dá origema uma nova arquitetura chamada “Segunda geração cliente/servidor”.

• O processo de construção de aplicações distribuídas é bem mais complexo que o desenvolvimentode aplicações não distribuídas devido ao maior número de parâmetros a serem definidos, aodesconhecimento da tecnologia e a falta de padrões e ferramentas que auxiliem essa ambientação.Portanto, muito tempo pode ser consumido no processo de definição e construção do ambiente dedesenvolvimento. Esse tempo é muitas vezes subestimado pelas empresas devido aodesconhecimento e as falsas propagandas dos vendedores de ferramentas.

Primeira geração cliente/servidor

Podemos definir cliente/servidor como uma arquitetura computacional que visa distribuir os recursos eo processamento de forma inteligente com o objetivo de otimizar o desempenho da rede e dossistemas, maximizando a utilização dos recursos de cada máquina e fornecendo uma base sólida eflexível para a implantação de um número crescente de serviços.Algumas implementações desse tipo já vêm sendo utilizadas em várias empresas e são conhecidascomo a primeira geração cliente/servidor.Para compartilhar recursos, como disco e impressora, são utilizados Servidores de Arquivos na rede.Estes são sistemas com a função de processar as requisições aos arquivos e impressoras e gerenciarseu acesso e distribuição.Além disso, parte do processamento das aplicações também foi distribuído. Alguns serviços demanipulação e gerenciamento de dados foram retirados das aplicações e colocados em pontoscentralizados conhecidos como “Servidores de Banco de Dados”, tornando o processamento dos dadosmais próximo do seu local de armazenamento. Os sistemas que fornecem tais serviços foram chamadosde “Sistemas Gerenciadores de Banco de Dados” - SGDB.Basicamente, a primeira geração de cliente/servidor se caracteriza por essa distribuição doprocessamento da aplicação entre dois componentes: a estação de trabalho do usuário e o servidor debanco de dados. À medida que a arquitetura cliente/servidor evolui, novas partes da aplicação vãosendo distribuídas e novos elementos vão aparecendo no ambiente.

Segunda geração cliente/servidor

Hoje, a tecnologia cliente/servidor já caminha para sua segunda geração. Essa geração explora mais oambiente de rede e suas máquinas. Surgem novos servidores com a finalidade de retirar das estaçõesde trabalho grande parte do processamento que elas realizam. Os principais elementos dessa novaarquitetura são os servidores de aplicação e os servidores “Web”.Os servidores de aplicação são responsáveis por retirar o restante da camada de manipulação de dadosque ainda havia na estação cliente. Além disso, tem o objetivo de concentrar a lógica de negócio, antesdistribuída entre a estação cliente e o servidor de banco. Normalmente, esse trabalho não é feito porum único servidor de aplicação e sim por um conjunto de servidores onde o processamento ébalanceado através de elementos chamados “Midlleware”. Desta forma resta para a estação cliente, oprocessamento da interface visual com o usuário, deixando-a mais leve, exigindo uma menorconfiguração e melhorando seu desempenho.

Os servidores “Web” tentam ir mais longe ainda, permitindo retirar das estações de trabalho até parteda lógica da interface visual, deixando-as responsáveis apenas por interpretar o código “HTML” enviadopelos servidores. Entretanto, com a utilização de componentes como Java e ActiveX, parte doprocessamento pode retornar à estação de trabalho.

Page 236: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

236

Essas novas tecnologias trazem mais recursos, mas tornam o ambiente mais complexo e difícil de serimplementado. É preciso estar bem certo do que se pretende e não fazer uso de uma tecnologia maisnova sem a conhecê-la direito ou sem a real necessidade de utilizá-la.

SGDB - Sistemas gerenciadores de banco de dados

Esse capítulo apresenta os sistemas gerenciadores de banco de dados, seus serviços, recursos emodelos.Os SGBDs são sistemas responsáveis em armazenar os dados e fornecer serviços capazes de manipulá-los. Para armazenar os dados em um disco, os SGBDs possuem uma forma estruturada padrão derepresentar os registros e campos, fornecendo serviços que permitem a criação e alteração dessasdefinições de dados. Fornecem ainda, um mecanismo interno para manter os dados no disco e parasaber onde está cada elemento em particular. Também são responsabilidades do SGDBs disponibilizarserviços para incluir, classificar, atualizar e eliminar os dados armazenados.Pela forma com que os dados são armazenados e de como eles se relacionam podemos classificar osSGBDs através de vários modelos até chegarmos aos bancos de dados relacionais.

Modelos de banco de dados

Analisando os diversos modelos de banco de dados, pode-se notar uma evolução no relacionamentoentre os dados, eliminando cada vez mais a redundância e proporcionando mais flexibilidade eportanto uma maior facilidade de manutenção das definições de dados. Para melhor entendermos osmodelos vamos utilizar os dados das três guias de pedidos da fig. 2.1.

Page 237: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

237

Fig. 2.1: Guia de Pedido.

Sistema de gerenciamento de arquivos

Esse é o único sistema que descreve como os dados são armazenados. Nesse modelo cada campo ouitem de dado é armazenado seqüencialmente no disco em um único e grande arquivo. Para encontrarum item de dado é necessário verificar cada elemento desde o início do arquivo. A única vantagemdesse método é sua simplicidade, já que seu formato muito se parece com o de um arquivo texto ondeas palavras se encontram escritas em uma determinada seqüência. Entretanto, por causa dessasimplicidade, muitos dados têm que ser escritos repetidamente gerando uma enorme redundância quedificulta a manutenção e a integridade dos dados. Não há também nenhuma indicação derelacionamento entre os dados, e o programador precisa saber exatamente como os dados estãoarmazenados para poder acessá-los de forma consistente. Além disso, sua estrutura física é rígida, oque dificulta alterações na definições dos dados, gerando a necessidade de reconstruir todo o arquivo.

1 | 20/10/96 | Ana Maria Lima | 999.876.555-22 | Caneta | 1010,00 | Lápis | 5 | 5,00 | 15,00 | 2 | 21/10/96 | Maria José |111.111-22 | Caneta | 15 | 15,00 | Caderno | ...

Fig. 2.2: Sistema de Gerenciamento de Arquivos.

Banco de Dados Hierárquico

Page 238: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

238

Nesse modelo, os dados são organizados em uma estrutura de árvore que se origina a partir de umaraiz. Essa estrutura identifica as relações “pai-filho” entre os vários itens do banco de dados, mostrandoassim suas vantagens sobre o modelo de gerenciamento de arquivos. No modelo hierárquico é possíveldefinir relações “de-um-para-muitos” que facilita e acelera o processo de pesquisa dos dados. Paraencontrar uma informação, não é mais necessário percorrer o arquivo inteiro. Basta examinar o itempedido, decompô-lo em componentes e descer pelos ramos necessários até encontrá-lo. Esse método,também facilita a inserção de novos dados, devido aos relacionamentos entre os campos serem feitosatravés de ponteiros. Para inserir um novo elemento basta alterar os ponteiros dos relacionamentosentre pais e filhos.

20/10/96

Raiz

1 2 3

15,00 CanetaAnaMaria Lápis

999.876.555-22 10 10,00 5 5,00

21/10/96 65,00 CanetaMariaJosé Caderno

111.111.111-22 15 15,00 5 50,00

Fig. 2.3: Banco de Dados Hierárquico.

Entretanto, esse método ainda possui alguns problemas. Cada nível da árvore é inicialmente definido equalquer alteração na estrutura desses níveis é uma tarefa difícil. Além disso, o problema daredundância de dados ainda não foi resolvido, já que esse modelo não implementa relações de“muitos-para-muitos”. No exemplo, podemos notar a repetição de algumas informações, o que dificultaa integridade e manutenção dos dados.

Banco de dados de rede

O modelo de rede descreve, conceitualmente, os banco de dados nos quais permitem relações de“muitos-para-muitos” entre os elementos de dados. Desta forma cada item possui um ponteiro para ositens com os quais se relaciona, eliminando assim a necessidade de qualquer tipo de redundância dedados. O grande problema desse modelo é a sua complexidade devido a flexibilidade existente em suasrelações. Quando o volume de dados começa a crescer, os relacionamentos entre os itens de dadosficam cada vez mais complexos, tornando sua visualização e entendimento cada vez mais difíceis.

Page 239: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

239

Raiz

1 2 3

A n aMar ia Lápis

999.876.555-22

MariaJoséCaderno

111.111.111-22

Caneta

Fig. 2.4: Banco de Dados de Rede.

Banco de dados relacional

Em 1969, foi publicado pelo Dr. E. F. Codd, o primeiro artigo que definia um modelo com base noconceito matemático dos conjuntos relacionais. A partir desse artigo, o modelo relacional tem sidorefinado, até que 1985 o próprio Dr. Codd lançou as “12 regras” que definiam um banco de dadosrelacional. Em 1990, foram publicadas as 333 regras que são subconjuntos e expansões das 12 regrasoriginais.O modelo relacional abandona o conceito de relações “pai-filho” feitas diretamente entre os dados e osorganiza em conjuntos matemáticos lógicos de estrutura tabular. Nesse modelo, cada item de dadopertence a uma coluna da tabela e uma linha da tabela é composta por vários elementos diretamenterelacionados.As tabelas também se relacionam através de funções matemáticas como JOINs e UNIONs. Para fazeresse relacionamento parte dos dados, que identificam unicamente o registro da tabela, são repetidosdentro da outra tabela.As vantagens desse método são sua simplicidade e flexibilidade nas definições das relações entre osvários itens de dados, já que não são feitos diretamente entre os dados e sim entre as tabelas.Entretanto, esse método não elimina por completo a redundância de dados, já que no mínimo osrelacionamentos entre as tabela são feitos através da repetição de parte dos dados. Além dessaredudância, fica a cargo do projetista do banco de dados se mais repetições de dados irão ou não fazerparte do modelo. O processo de fragmentação dos dados, a fim de serem organizados emsubconjuntos (tabelas), é conhecido como normalização.

Page 240: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

240

PedidoNumPed Data Valor

123

20/10/9621/10/9622/10/96

Cliente

15,0065,0025,00

122

ClienteCodigo Nome CPF

12

Ana Maria LimaMaria José

999.876.555-22111.111.111-22

ItensNumPed Produto Quantid.

112

CanetaLápisCaneta

Valor

10515

10,005,0015,00

23

CadernoLápis

515

50,0015,00

3 Caderno 1 10,00

Fig. 2.5: Banco de Dados Relacional.

Os bancos de dados relacionais vêm se tornando um padrão no mercado, servindo como base de dadospara a maioria dos sistemas das empresas. A cada dia, mais ferramentas são construídas para tirarproveito dessa tecnologia, fazendo surgir um número crescente de recursos e produtos a seremoferecidos para os usuários. Pode-se dizer então, que esta é uma tecnologia sólida e consistente e queirá acompanhar o mercado por um longo período de tempo. No entanto, é uma tecnologia quecontinua evoluindo com o objetivo de disponibilizar as informações para os usuários de maneiraeficiente, viabilizando o negócio da corporação e descentralizando as tomadas de decisão.

A linguagem SQL

Para acessar os bancos de dados relacionais foi desenvolvida uma linguagem chamada SQL. O Objetivodessa linguagem é fornecer uma forma padrão de acesso aos bancos de dados, não importando alinguagem com que esses tenham sido desenvolvidos. Apesar da tentativa de se tornar um padrão(ANSI), cada fornecedor hoje possui uma série de extensões que tornam as várias versõesincompatíveis entre si. Por isso, não pense que uma aplicação construída para acessar um determinadobanco de dados de um fornecedor, irá acessar também, sem qualquer modificação, o banco de dadosde um outro fornecedor. Isto só é possível se a aplicação utilizar somente a parte comum (ANSI) dalinguagem SQL, mas isto faz com que ela perca vários recursos importantes disponíveis em cada versãoSQL de fornecedores diferentes. Alguns bancos de dados já suportam o padrão SQL ANSI-92 que já émais abrangente numa tentativa de facilitar o processo de deixar transparente a base de dadosutilizada pela aplicação. Entretanto, alguns fornecedores ainda não fornecem suporte ao SQL ANSI-92de forma completa porque teriam que alterar partes estruturais de seus sistemas gerenciadores.

Categorias da Linguagem SQLA linguagem SQL se divide em três categorias:

• DDL ( Linguagem de Definição de Dados). Parte da linguagem com comandos para criação dasestruturas de dados como as tabelas, colunas, etc. Ex: CREATE TABLE.

Page 241: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

241

• DML ( Linguagem de Manipulação de Dados). Parte da linguagem com comandos para acessar ealterar os dados armazenados no banco de dados. Os principais comandos dessa categoria são:SELECT, UPDATE, INSERT, DELETE.

• DCL ( Linguagem de Controle de Dados). Parte da linguagem com comandos para definir usuáriose controlar seus acessos aos dados. Ex: GRANT.

Consistência e integridade dos dados

A maioria dos bancos de dados relacionais possuem recursos para consistir e tornar íntegro os dadosarmazenados em suas tabelas. Desta forma, qualquer ferramenta que o usuário utilizar para acessá-loé obrigada a respeitar as regras, mantendo a integridade dos dados. Os recursos de consistênciavariam de banco para banco, mas pode-se definir conceitualmente algumas categorias de integridadecomo: integridade referencial, domínios e regras do negócio.

Integridade Referencial

Integridade referencial é um conjunto de regras e de consistências entre os registros de duas tabelasque se relacionam. Como foi visto no modelo relacional, quando duas tabelas se relacionam, a chaveprimária de uma é copiada para a outra e se esses dados forem alterados ou excluídos da tabelaoriginal é necessário verificar o que será feito com os dados e registros duplicados na outra tabela.Quando se define uma integridade referencial, está se definindo o procedimento que será tomadoquando esses processos ocorrerem.Sejam duas tabelas “A” e “B” que se relacionam através de uma coluna “c” que é a chave primária de“A” e portanto foi repetida em “B” para se fazer o relacionamento. Quando se define uma integridadereferencial para esse relacionamento, está se definindo que a coluna “c” da tabela “B” só pode contervalores já cadastrados na coluna “c” da tabela “A”.

Tabela B*a b c

Tabela A

d e . .

*c

Fig 3.19: Integridade Referencial.

Existem três formas de se manter essa regra quando registros da tabela “A” são excluídos:

Page 242: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

242

• Restrict: Define que se o valor da coluna “c” de “A” existir em algum registro de “B”, o registronão poderá ser excluído e uma mensagem de erro retornará para a aplicação;

• Cascade: Define que se o valor da coluna “c” de “A” existir em algum registro de “B”, todos osregistros que possuírem esse valor serão também excluídos;

• Set Null: Define que se o valor da coluna “c” de “A” existir em algum registro de “B”, os valores de“c” em todos os registros serão transformados para “Null”;

Em todos os casos, se o usuário tentar inserir um registro em “B” com um valor de “c” que não existana tabela “A”, um erro será reportado à aplicação.Alguns bancos, também permitem fazer o mesmo tratamento quando a chave da tabela for alterada,ao invés de excluída. Entretanto, essa alteração de chaves não deve ser um processo comum nasaplicações, sendo normalmente proibidas.Os bancos de dados possuem formas diferentes de disponibilizar esses serviços. Alguns possuem atémais de uma forma de fazer o mesmo processo. Mas de maneira geral existem duas possibilidades deimplementação:

Integridade Referencial Declarativa

Essa é uma forma mais fácil, porém menos flexível. Com apenas um comando se define a integridade.Porém, alguns bancos não suportam essa sintaxe ou a fornecem de maneira limitada somente pararegras do tipo “Restrict”. A maior vantagem dessa alternativa é sua simplicidade e por isso menossujeita a erros de implementação.

Triggers

Os triggers são pedaços de código escritos em uma extensão da linguagem SQL fornecida por cadafornecedor, sendo portanto uma linguagem proprietária. Essa extensão possui instruções paraimplementar “loops” e verificar condições permitindo fazer pequenos programas estruturados. Ostriggers são disparados automaticamente pelo banco quando eventos de inclusão, alteração ouexclusão ocorrem em uma determinada tabela. Portanto, através dos triggers pode-se desenvolver alógica necessária para se manter a integridade referencial entre as tabelas.

Domínio dos dados

Outro tipo de consistência é com relação ao domínio dos dados. Para um determinado campo de dadopode existir um conjunto de valores permitidos e o banco de dados deve reportar um erro à aplicaçãose um valor inválido for informado. Um tipo de consistência de domínio que é normalmente fornecidopelos bancos é a possibilidade do campo ser nulo ou não. Alguns bancos possuem também comandospara definir um conjunto de valores válidos para um determinado campo. Ex: Valores (‘J’,’F’) para umcampo que armazena se a pessoa é física ou jurídica. Outros possuem uma sintaxe para definir valoresmínimos e máximos. Pode-se, ainda, utilizar o recurso de triggers para esse propósito.

Page 243: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

243

Regras de Negócio

Pode-se definir como regras de negócio a integridade que deve existir entre os valores de mais de umcampo de uma ou mais tabelas. Pode-se considerar como regra do negócio as consistências eatualizações que devem ser feitas em várias tabelas, quando um registro é inserido, alterado ouexcluído de uma tabela. Ou um processo de cálculo disparado sobre os dados do banco que tambémfazem atualizações em diferentes locais, mas de forma a manter os valores dos dados sempre íntegrose consistentes. Um exemplo seria a atualização de estoque que normalmente envolve outras tarefas emum sistema de controle de estoque.Para implementar essas regras de negócio no banco de dados são utilizados os recursos de triggers estored procedures. Stored procedures são blocos de código assim como os triggers. A diferença entreeles é que os triggers são disparados automaticamente por inserções, alterações e exclusões feitas nastabelas, enquanto as stored procedure são chamadas explicitamente pela aplicação.

Distribuição da consistência e integridade dos dados

Como foi visto, é possível implementar várias regras de consistência dos dados no próprio banco dedados. Entretanto, é possível implementá-las também na aplicação e portanto fica uma dúvida de qualseria o melhor lugar para implementá-las. Ambas as alternativas possuem vantagens e desvantagensque devem ser observadas no início do processo de desenvolvimento.A principal vantagem em se colocar todas as regras no banco de dados é que esse mantém aconsistência e integridade dos dados independente da ferramenta de acesso utilizada pelo usuário.Além disso, as manutenções dessas regras ficam localizadas em um único local, ao invés de ficaremespalhadas por toda a aplicação ou por diversas aplicações. Entretanto, o desenvolvimento utilizandoessa linha de trabalho é muito mais árduo e demorado. As ferramentas disponíveis nesse ambiente nãoapresentam ainda muitos recursos que dêem produtividade na construção das regras. As linguagensutilizadas para escrever as “stored procedures” e “triggers” são proprietárias dos fornecedores,tornando a empresa dependente de único fornecedor, dificultando a distribuição dos dados em bancosde fornecedores diferentes. Além disso é necessário dividir o desenvolvimento em duas linguagens. Alinguagem da ferramenta para se montar a interface e a chamada dos processos e a linguagem paraconstrução das “stored procedures”.Atualmente, o mercado se encontra dividido com cada empresa tomando um caminho diferente paradistribuir essas regras entre o cliente e o servidor. Mas não pode-se dizer que um caminho já seguidopor uma empresa que obteve sucesso é o mais indicado para uma outra empresa. Muitas outrasvariáveis precisam ser consideradas e dificilmente serão iguais entre duas empresas. Além disso, asferramentas e a tecnologia evoluem fazendo como que um mesmo caminho possa obter resultadosdiferentes, considerando-se a tecnologia atualmente disponível.De uma maneira geral, as duas primeiras categorias de consistência (integridade referencial edomínios) são normalmente implementadas no banco de dados, sendo que os domínios sãoimplementados repetidamente na aplicação para evitar que os comandos sejam enviados ao banco. Agrande dúvida mesmo, é com relação às regras de negócio que algumas empresas implementamtotalmente no banco de dados, outras totalmente na aplicação e algumas distribuem entre esses doiscomponentes. Atualmente, existe mais um alternativa na nova geração da arquitetura Cliente/Servidor:a implementação das regras de negócio em um novo componente chamado “Servidor de Aplicações”.

Trabalhando com Bancos de Dados Relacionais

Os bancos de dados relacionais fornecem um conjunto de serviços para que as aplicações possamacessá-los e manipulá-los. Portanto, é importante entender bem sua funcionalidade para melhoraproveitar seus recursos nas aplicações. Existem algumas diferenças na forma de trabalhar entre osfornecedores, mas grande parte dos conceitos podem ser aplicados a todos os bancos de dadosrelacionais.

Page 244: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

244

Componentes da arquitetura cliente/servidor - dlsf

Como foi visto, a arquitetura cliente/servidor é composta de dois componentes físicos que secomunicam através da rede: a estação de trabalho do usuário e o servidor de banco de dados.Para se estabelecer a comunicação entre esses dois componentes são utilizadas várias camadas desoftware que são instaladas em cada componente físico. A estação de trabalho cliente deve ter, alémda aplicação final, vários outros elementos para acessar a base de dados em um SGBD através de rede.

• Database Engine: biblioteca fornecida pelo fornecedor da ferramenta de desenvolvimento com oobjetivo de fornecer uma forma única e transparente da aplicação acessar diferentes bases dedados. Ex: BDE (Borland Database Engine), ADO ou DBExpress;

• Drivers de conexão responsável pela comunicação com a fonte de dados. Sua principalcaracterística é traduzir os comandos utilizados pelo Database Enginer para comandos conhecidospela base de dados utilizada.

• Client do banco de dados: API fornecida pelo fornecedor do SGDB e instalada na estação clientepara estabelecer a comunicação com o banco de dados. Nessa API se encontram as funções deacesso a base de dados. É também, responsável por utilizar um determinado protocolo de redepara encontrar o servidor de banco para que a aplicação possa acessá-lo enviando comandos ebuscando os dados.

• Protocolo de rede: softwares responsáveis pela transmissão dos dados pela rede entre a máquinacliente e o servidor.

CLIENTE

Sistema Operacional

CLIENTE MIDDLEWARE

SQL/APISQL/API

SERVIDOR

Sistema Operacional

SERVIDOR

NetBiosNetBios TCP/IPTCP/IP IPX/SPXIPX/SPX SNASNA

RPCRPC MensagensMensagens SegurançaSegurança

Transporte

Serv. DiretórioServ. DiretórioSOR

Serviços Específicos

Serv. DiretórioServ. Diretório

FerramentasDesenvolvimento

Aplicações

Banco de DadosBanco de Dados

Database EnginerDatabase Enginer

Projetando Aplicações Cliente/Servidor

A construção de aplicações Cliente/Servidor deve obedecer algumas regras de organização para que ossistemas possam ter um tempo de vida mais longo e acompanhar a evolução do negócio da empresa ea evolução tecnológica da arquitetura.

Page 245: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

245

Esse capítulo mostra algumas técnicas de construção de aplicações voltadas para o ambiente cliente/servidor.

Estrutura de uma Aplicação

Como foi visto, o ambiente cliente servidor permite que a aplicação seja distribuída entre doiscomponentes físicos: a estação cliente e o servidor de banco de dados. Entretanto, logicamentepodemos identificar três camadas distintas dentro de uma aplicação.

ApresentaçãoComposta por componentes responsáveis pela interação da aplicação com o usuário final. Éresponsabilidade dessa camada receber os dados e comandos do usuário e devolver-lhe informaçõesatravés de elementos visuais como consultas, gráficos, relatórios e etc;

Lógica do Negócio

Parte da aplicação responsável por manter as regras de negócio da empresa. Essa camada recebe osdados da camada de interface e executa as operações e validações necessárias para enviá-los ao bancode dados. Da mesma forma, extrai os dados do banco de dados de acordo com as regras de negócioda aplicação e os envia para elementos da interface para que sejam exibidos.Portanto, essa camada é responsável em interligar a interface visual com o banco de dados através daexecução de transações, consistência dos dados e regras de negócio, ou seja, a parte funcional daaplicação.

Gerenciamento de Dados

Parte da aplicação responsável pelo acesso e a manipulação dos dados no servidor. Como já foi vistoanteriormente, grande parte dessa camada é implementada pelo próprio servidor de banco de dados.Normalmente o acesso aos serviços é feito através da linguagem SQL. Porém, é também necessário umconjunto de comandos para enviar as sentenças SQLs e gerenciar a comunicação entre a aplicação e oservidor. Esses comandos se encontram em bibliotecas disponibilizadas pelos próprios fornecedores debanco de dados que são instaladas em cada estação de trabalho. Além disso cada fabricante deferramentas de desenvolvimento fornece também métodos e componentes capazes de simplificar etornar mais transparente o acesso aos diversos SGDBs.

LÓGICA do NEGÓCIO

GERENCIAMENTO de DADOS

APRESENTAÇÃO

CLIENTE

SERVIDOR

LÓGICOFÍSICO

Fig 6.1: Camadas Físicas e Lógicas de uma Aplicação.

Page 246: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

246

Vantagens da organização da aplicação em camadas

A divisão da aplicação nessas três camadas lógicas possibilita a organização e padronização dacodificação e construção da aplicação, além de proporcionar uma maior facilidade de manutenção eevolução para novas fases da arquitetura cliente/servidor. Como já foi visto, a tendência da arquiteturaCliente/Servidor é retirar cada vez mais parte do processamento da aplicação realizado pelas estaçõesde trabalho clientes e centralizá-lo em servidores, provendo um melhor gerenciamento do processo efacilitando a evolução da funcionalidade que foi distribuída.A distribuição da aplicação em camadas lógicas possibilita também que cada camada possa evoluirindependente das outras desde que se mantenha a interface entre elas. Por exemplo, pode-se alteraras regras de negócio para atender as necessidades do mercado sem necessariamente ter que modificara camada de interface ou a camada de gerenciamento de dados. Por outro lado, pode-se evoluir aapresentação para novas tecnologias como multimídia, sem precisar alterar as regras de negócio.Evoluções tecnológicas, como a distribuição da base de dados na camada de gerenciamento de dadospode ser feita de forma transparente das demais camadas. Portanto, esses tipos de distribuição tornamas aplicações mais escaláveis para suportar futuras implementações possibilitando um tempo de vidamuito mais longo.

Construindo Aplicações Cliente/Servidor

Existem várias maneiras de se utilizar os componentes do Delphi para trabalhar com banco de dados. Épreciso saber escolher as formas mais adequadas para cada tipo de implementação. Através dessetópico serão mostrada várias dessas opções e o que cada uma difere no comportamento da aplicaçãocom o banco de dados.

O aplicativo que iremos construir é um controlador de desenvolvimento de aplicativos (projetos). Nelevocê poderá inserir os membros de um projeto de desenvolvimento, cadastrar bugs encontrados e suascorreções, bem como cadastrar tarefas a serem realizadas. Unicamente para efeito de comodidadeusaremos o Interbase 6.0 como SGDB, pois praticamente toda instalação do Delphi/Kylix tambémcontém o Interbase. Certamente poderíamos utilizar o MS SQL Server ou Informix, sempre trabalhandoda mesma maneira2.

O modelo de dados abaixo ilustra a estrutura de nosso banco Interbase.

2 Se você possui uma instalação do Firebird poderá usá-lo normalmente para este exemplo.

Page 247: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

247

Como dito anteriormente, o aplicativo gira em torno de projetos de desenvolvimentos. Cada projetopossui membros a ele ligados, isto é, desenvolvedores que nele trabalham. Cada projeto é de umdeterminado tipo, como, por exemplo, “Delphi – ADOExpress e MS SQL Server”, “Delphi - aplicativosdistribuídos” ou “Delphi – desenvolvimento de site”. Os projetos possuem tarefas a serem executadas ebugs a serem corrigidos. Cada bug detectado possui seu próprio histórico, quer dizer, possui uma listade ações que foram feitas no sentido de sua fixação. Veja abaixo a descrição de cada um dos camposdas tabelas do banco “BUGS”.

PROJETOSCampos Descrição

CDPROJ Código exclusivo do projetoNMPROJ Nome completo do projeto.CDNMPROJ Codinome do projeto.DATAPROJ Data de cadastro do projeto do sistema.CDTPPROJ Código do tipo de projeto.CDDES Código do desenvolvedor-chefe do projeto.STATUSPROJ Status do projeto (1 – Em andamento, 2 – Paralizado, 3 – Encerrado).

DESENVOLVEDORESCampos Descrição

CDDES Código exclusivo do desenvolvedorNMDES Nome completo do desenvolvedor.

TIPOPROJETOSCampos Descrição

CDTPPROJ Código exclusivo do tipo de projeto.DSCTPPROJ Descrição do tipo de projeto.

Page 248: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

248

MEMBROSCampos Descrição

CDMBR Código exclusivo do membro do projeto.CDPROJ Código do projetoCDDES Código do desenvolvedor.ATIVO Determina se o membro está ativo no projeto ou não.

TODOCampos Descrição

CDTDO Código exclusivo da tarefa.CDPROJ Código do projeto.NMTDO Nome da tarefa.DSCTDO Descrição completa da tarefa.DATATDO Data de inserção da tarefa.CDDES Código do desenvolvedor que inseriu a tarefa.CDRES Código do desenvolvedor que executará a tarefa.FIXADO Indica se a tarefa foi executada.DATAFIX Data em que a tarefa foi terminada.

TIPOBUGSCampos Descrição

CDTPBUG Código exclusivo do tipo de bug.DSCTPBUG Descrição do tipo de bug.

BUGSCampos Descrição

CDBUG Código exclusivo do bugCDPROJ Código do projeto.NMBUG Nome do bugCDTPBUG Descrição completa do bug.DATABUG Data de inserção do bug.DSCBUG Descrição completa do bug.CDDES Código do desenvolvedor que inseriu o bug.CDRES Código do desenvolvedor que fixará o bug.FIXADO Indica se o bug foi fixado.

HISTORICOCampos Descrição

CDHIS Código exclusivo do histórico do bug.CDBUG Código do bug.BUGHIS Nome do histórico do bug.DATAHIS Data de inserção do histórico do bug.CDDES Código do desenvolvedor que inseriu o histórico do bug.

Utilizando Interbase Express

Utilizaremos a Interbase Express como mecanismo de acesso ao dados de nosso banco de dados. Estaescolha é baseada principalmente pelo fato de a Interbase Express fornecer o mais rápido mecanismode acesso a bancos de dados Interbase/Firebird disponível.

Page 249: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

249

Crie um novo projeto e salve-o como o nome “Bugs”. O formulário principal pode ser salva com o nome“Main.pas”. Como sempre ocorre em aplicativos que acessam bancos de dados, é importante inserir ummódulo de dados no nosso aplicativo. Para a arquitetura cliente/servidor, nós usamos módulos dedados “comuns”, pois grande parte da lógica comercial estará inserida no aplicativo cliente. Assim, todaa lógica de negócio fica concentrada em um único ponto da aplicação, facilitando sua manutenção e aimplementação de novos recursos. Para aplicações maiores é aconselhável a utilização de mais de umMódulo de Dados, o que possibilita a divisão da lógica comercial em partes logicamente distintas.

Insira o novo módulo de dados através dos menus “File | new | Data Module”; renomeie-o para “DM” esalve a unidade com o nome “DataModule”.

Componente TIBDatabase

Como foi visto anteriormente, o componente TIBDatabase é o responsável pela conexão com o bancode dados. Esse componente possui algumas propriedades que permitem a configuração dessa conexão.Insira um TIBDatabase no nosso módulo de dados e configure suas propriedades de conexão. Amaneira mais fácil de fazer isto é através do editor de propriedades deste componente. Você podeacessá-l0 dando um duplo clique em cima do TIBDatabase no nosso módulo de dados. Veja abaixouma imagem deste editor de propriedades.

Através deste editor, é possível configurar as propriedades DatabaseName, LoginPrompt e Params deum TIBDatabase de uma só vez. Insira também um componente TIBTransaction e ligue-o aocomponente TIBDatabase. Renomeie este componente para “TrsDefault”.

Vamos agora inserir todos os datasets que serão responsáveis pela exibição e edição dos dados dastabelas TIPOPROJETO, TIPOBUGS e DESENVOLVEDORES. Devido ao fato de estas tabelas fornecereminformações ao outras através de chaves estrangeiras, elas são genericamente chamadas tabelas depesquisa. Insira 4 componentes TIBDataset, 1 componente TIBSQL, 5 componentes TIBTransaction e 3componentes TDataSource. A conexão entre estes componentes é feita da seguinte forma:

Page 250: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

250

• Todos componentesTIBDataset são conectados a um componente de conexão através dapropriedade Database. São conectados a um componente TIBTransaction através da propriedadeTransaction.

• Todos os componentes TIBTransaction são conectados a um componente de conexão através dapropriedade DefaultDatabase.

• Todos os componentes TDataSource são ligados a um dataset através da sua propriedade Dataset.

• O componente TIBSQL é conectado a um componente de conexão através da sua propriedadeDatabase e a um TIBTransaction através da sua propriedade Transaction.

Renomeie todos estes objetos, seguindo uma nomenclatura padrão que lhe pareça razoável. Énecessário agora inserir os comando “Select” para todos os componentes TIBDataset que inserimos.Este componente possui suporte para comandos de seleção, alteração, deleção e atualização de tabelasInterbase através das propriedades SelectSQL, UpdateSQL, DeleteSQL e RefreshSQL, respectivamente.Estas propriedades devem ser preenchidas. A maneira mais fácil de fazer-se isto é digitar o comandoSelect e, em seguida, no menu de contexto que aparece ao clicar-se sobre o componente TIBDataset,escolher o item “Dataset Editor” para acessar um editor que lhe facilitará sobremaneira esta tarefa.Este editor é capaz de gerar comandos SQL para você a partir de algumas poucas informações obtidaspreviamente. Após fazer tudo isto, você pode testar seu trabalho alterando a propriedade Active de umTIBDataset para True.

O componente TIBSQL inserido será usado para executar comandos dinamicamente, durante aexecução do aplicativo. Da mesma forma, um componente TIBDataset (que nomeamos “DsSearch”)será usado paraexecutar consultas ao banco de forma dinâmica. Portanto, as suas propriedades que sereferem aos comandos SQL a sererm usados não serão preenchidas agora.

Projeto de interface do software

Agora que temos um módulo de dados minimamente desenvolvido, podemos começar a pensar nainterface (GUI) do nosso aplicativo.

Número de Tabelas AcessadasUm outro fator relevante na escolha do componente, é o número de tabelas que devem ser acessadaspara buscar as informações necessárias para o usuário em uma mesma tela. Até um certo número detabelas é mais interessante utilizar o recurso de “joins” dos bancos para trazer em um único comandoSQL, todo o conjunto de informações. Nesse caso um componente TQuery deveria ser utilizado.Quando isso é feito através de vários componentes TTable, é as vezes necessário trazer os dados detodas as tabelas para a máquina cliente para que a relação entre elas possa ser feita. No melhor caso,se filtrarmos cada tabela pelo registro selecionado na outra, teríamos que executar vários comandosSELECTs mais simples no servidor contra um único comando um pouco mais complexo do componenteTQuery.

Trabalhando com o TQuery

O componente TQuery pode ser então utilizado para acessar e manipular os dados. Como foi visto, autilização desse componente deixa mais flexível o acesso ao banco, já que trabalha diretamente com a

Page 251: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

251

linguagem SQL. Portanto, manutenções evolutivas como acessar mais de uma tabela através do mesmocomponente podem ser implementadas com mais facilidade.Afim de continuarmos nossa aplicação, devemos colocar um componente TQuery no DataModuleDMSistVendas.

Fig 7.3: Componente TQuery

Componente Propriedade ValorQuery1 Name QProduto

DatabaseName DBVENDASSQL Select * from produto order by

produto.prod_cdRequest Live TRUEActive TRUE

A propriedade Request Live ligada, faz com que o Delphi tente atualizar automaticamente o “resultset” trazido pela “query”. Desta forma, o componente TQuery se comporta de forma semelhante aocomponente TTable.Entretanto, para que isso seja possível, o comando SQL tem que obedecer algumas restrições como porexemplo:

• Conter apenas uma tabela na cláusula From;

• Não possuir agregações através de group by e funções como sum, max, etc.

Após termos preenchido o DataModule com os componentes responsáveis pelo acesso ao banco dedados, podemos construir o “form” de manutenção da tabela de produto como a figura a seguir:

Page 252: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

252

Fig 7.4: Form de Produto.

Componente Propriedade ValorForm1 Name frmProduto

Caption ProdutosPanel1 Align alTop

CaptionPanel2 Align alClient

CaptionDataSource1 Name DSMain

DataSet DMSistVendas.QprodutoDBNavigator1 DataSource DSMainDBEdit1..DBEdit4 DataSource DSMain

DataField pro_cd..pro_estoque

Podemos então executar a aplicação e verificar que através da propriedade Result Live do Qproduto,foi possível atualizar os dados e acrescentar novas linhas à tabela. Entretanto, podemos notar que aslinhas inseridas desaparecem do “Result Set” ao navergarmos para outro registro. Esta é uma restriçãoque existe no componente TQuery quando se utiliza a propriedade Result Live para torná-loatualizável automaticamente pelo Delphi. Além disso, foi visto que para ser possível tornar o “result set”atualizável, existem algumas restrições quanto ao comando SQL definido.Por causa desses motivos, talvez seja então necessário trabalhar com a propriedade Result Live iguala “False” e utilizar um outro artifício para tornar o “result live” atualizável sem restrições no comandoSQL e sem perder as linhas inseridas.

Page 253: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

253

CC AA PP ÍÍ TT UU LL OO 22 11 -- CC RR II AA NN DD OO AA PP LL II CC AA ÇÇ ÕÕ EE SS MM UU LL TT II -- CC AA MM AA DD AA SS

Page 254: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

254

Escrevendo aplicações distribuídas

Modelos de thread e instanciação de objetos

Módulos de dados remotos

Instanciação única

Instanciação interna

Instanciação múltipla

Modelo de thread simples

Modelo de thread Apartment

Modelo de thread livre

Modelo de thread neutro

Modelos de thread em CORBA

Modelo de thread simples

Modelo de thread múltiplo

Page 255: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

255

Page 256: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

256

CC AA PP ÍÍ TT UU LL OO 22 22 -- CC RR II AA NN DD OO UU MM AA AA PP LL II CC AA ÇÇ ÃÃ OO PP OO RR TT AA -- AA RR QQ UU II VV OO SS

Page 257: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

257

Page 258: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

258

Í n d i c e r e m i s s i v o

.

.NET · 16, 18, 19, 73, 156, 157, 158, 189

A

ActiveXDataObjetcs · Consulte ADOADO

Arquitetura · 148Conectando com uma fonte · 151Conhecendo · 149Framework · 147, 148, 150Interface de programação · 149Modelo de objetos · 150

ADOExpress · 147, 150, 158Componentes · 150Conectando com fontes de dados ADO · 151Conhecendo · 150

Aplicações console · 17, 30, 77

B

BDE · 17, 37, 77, 79, 80, 119, 120, 121, 123, 134,138, 139, 140, 141, 142, 143, 144, 145, 159, 173,181, 204, 207BDE Administrator · 140, 144Cahcing Blob's · 142Database Desktop · 145Datasets · Consulte DatasetsDrivers · 139Ferramentas BDE · 143Handles · 142Manipulando transações com · 142Passthrough SQL · 143Recursos avançados · 141Seu futuro · 145SQL Explorer · 144SQL Monitor · 144Transações locais em · 143

C

C++ · 19, 20, 31, 35Classes

Conversões implícitas · 50Conversõs · 49

Code Editor · 24Code Insight · Consulte IDECOM · 148

DCOM · 124, 129, 130, 132, 133, 147, 149COM+ · 16, 17, 49, 73, 130, 132Componentes

Palheta de Componentes · 26Console · Consulte Aplicações consoleCORBA · 129, 131, 189, 254

D

DatasInterpretando horas · 56Rotinas de trabalho com · 55Trabalho com · 54

DatasetsBaseados em BDE · 140Baseados em DBExpress · 181Baseados em Interbase Express · 160Entendendo datasets · 134Eventos de · 136Famílias de · 134Query-type datasets · 135Stored procedure-type datasets · 136Table-type datasets · 135Tipos de · 135

DBExpress · 17, 20, 79, 80, 119, 120, 121, 123, 134,145, 180, 181, 182, 183, 186, 205Arquitetura · 181Datasets unidirecionais · 181Drivers · 182Executando comandos · 187Parâmetros de conexão · 183Preparando datasets · 186Usando stored procedures · 185Usando tabelas · 185

DCOM · Consulte COMDelphi

Ambiente de programação · 23Delphi 7.0 · 18Delphi.NET · 18Enterprise · 18IDE · 23Janela principal · 23Professional · 18Standard · 18

E

EOP · 35

F

FerramentasBDE · Consulte BDE

Firebird · 20, 120, 121, 134, 139, 159, 160, 161, 162,167, 173, 174, 175, 176, 177, 181, 205, 213

Page 259: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

259

I

IBX · Consulte Interbase ExpressIDE

Appbrowser · 32Code Insight · Consulte IDEEncaixe de janelas · 31Navegação entre seções · 32Preenchimento de classes · 31TO-DO List · 33

Interbase · 17, 20, 78, 88, 120, 121, 134, 136, 138,139, 147, 149, 152, 159, 160, 161, 162, 163, 167,168, 173, 174, 175, 176, 177, 178, 181, 183, 204,205, 213Generators · 162

Interbase Express · 20, 159, 160, 161, 162, 173, 175,177, 204Arquitetura · 161Conexões com bancos usando · 174Datasets unidirecionais · 162E compatibilidade inter-plataformas · 173Extensibilidade · 162Níveis de isolamento de transações · 175Transações com a · 174Usando comandos com · 176

InterbaseAdmin · 177, 178

K

KylixKylix 3.0 · 20O que é? · 19Open Edition · 21usando C++ · 20versões · 21

M

Microsoft.NET · 18

Modelos de interface · Consulte SDI e MDIMS Acess · 225, 226, 227, 229

O

Object Inspector · 24Object Pascal · 34

Arquivos de código-fonte · 29Arquivos do compilador · 30Orientação a objetos · 35

Object Repository · 27Object Treeview · 25OLEDB · Consulte ADO

Componentes da tecnologia · 149Interface de programação · 149Provedores de dados · 149

OOP · 26, 35, 38Ação · 36

Atributos · 36Embutimento · 36Encapsulamento · 36Herança · 36Objeto · 35Polimorfismo · 36

Orientação a objetos · Consulte OOP

P

Palheta de Componentes · 26Project Manager · 28

S

SDI · 31SOAP · 18, 129, 189Strings

Concatenando strings · 51Copiando strings · 52Deletando strings · 53Formatando strings · 53Inserindo strings · 53Manipulação de · 52

T

TADOCommand · 74, 147, 150, 151, 154, 155, 156TADOConnection · 147, 150, 151, 152, 153, 154

Conectando com uma fonte de dados via · 151Connection Editor · 152ConnectionString · 151

TADODataset · 134, 136, 151, 154, 156TADOQuery · 134, 136, 151, 154TADOStoredProc · 134, 136, 151TADOTable · 134, 135, 151TBDEClientDataset · 136, 140, 204TClientDataset · 136, 189, 191, 195, 202, 205TCustomADODataset · 134TCustomClientDataset · 135TCustomSQLDataset · 134TDatabase · 140, 141, 143

e TSession · 140Métodos · 141

TDataSource · 176TIBBackupService · 161, 178TIBConfigService · 161TIBCustomDataset · 134, 161TIBDatabase

Propriedades de · 174Usando o Database Editor · 174

TIBDataBase · 161TIBDataBaseInfo · 161TIBDataset · 134, 136, 161, 162, 174, 204, 205TIBDataSet · 161TIBEvents · 161TIBExtract · 161TIBGenerator · 162, 163, 164, 165, 166, 167, 168,

169, 170, 171, 172, 173

Page 260: Curso

SGDB - Sistemas Gerenciadores de Banco de Dados

260

TIBInstall · 161TIBLicensingService · 161TIBLogService · 161TIBQuery · 74, 134, 136, 161, 165, 166, 172TIBRestoreService · 161, 178TIBSecurityService · 161TIBServerProperties · 161TIBSQL · 161, 163, 164, 165, 166, 168, 169, 170,

171, 176, 177Comandos com · 176Métodos de · 177

TIBSQLMonitor · 161TIBStaticalService · 161TIBStoredProc · 134, 136, 161TIBTransaction · 161, 163, 174, 175, 176

Transaction editor · 175TIBUninstall · 161, 178TIBUpdateSQL · 161TIBValidationService · 161Tipos de dados · 43

Arrays · 46Arrays dinâmicos · 47Conjuntos · 46Records · 47Tipo boolean · 45Tipo variant · 48Tipos estruturados · 45Tipos real · 44Tipos simples · 44Tipos string · 45Tipos subrange · 44

TNestedTable · 134TO-DO List · Consulte IDETQuery · 134, 140Transações

em BDE · 142Transações locais com BDE · 143Usando Interbase Express · 174

TSession · 140, 141TSQLConnection · 182, 183, 187TSQLDataset · 134, 136, 181, 182, 184, 185, 187, 205TSQLQuery · 134, 136, 181, 182, 184, 187TSQLTable · 134, 135, 181, 182, 185TStoredProc · 134, 136, 140, 143TTable · 74, 134, 140, 223

U

UDA · 148Unidades PAS

Referências circulares · 40Seção Finalization · 40Seção Implementation · 39Seção Initialization · 39Seção Interface · 39

Universal Data Acess · Consulte UDA

V

Visual Basic · 31, 35

W

WEBServices · 18, 19, 20, 21, 189