93909254 GENEXUS Heuristica Apostila Teorica

409
1 Introdução Teórica

Transcript of 93909254 GENEXUS Heuristica Apostila Teorica

Page 1: 93909254 GENEXUS Heuristica Apostila Teorica

1

Introdução Teórica

Page 2: 93909254 GENEXUS Heuristica Apostila Teorica

2

Ferramentas e Metodologias

Nossa tarefa como profissionais de informática consiste em desenvolver e manter aplicações para apoiar ao usuário na sua atividade. Para realizar esta tarefa existem diferentes ferramentas e metodologias.

GeneXus é uma ferramenta para o desenvolvimento de aplicações sobre bases de dados. Seu objetivo é permitir a implantação de aplicações no menor tempo e com a melhor qualidade possível.

Em linhas gerais, o desenvolvimento de uma aplicação implica tarefas de análise, desenho e implementação. A maneira do GeneXus alcançar o objetivo anterior é liberar as pessoas das tarefas automatizáveis (como o desenho da base de dados), permitindo assim se concentrar nas tarefas realmente difíceis e não automatizáveis (como compreender os problemas do usuário).

GeneXus emprega uma metodologia que tem um enfoque muito diferente das metodologias mais utilizadas. Aprender a utilizar GeneXus adequadamente vai além de conhecer uma nova linguagem: o mais importante é aprender sua metodologia.

Page 3: 93909254 GENEXUS Heuristica Apostila Teorica

3

VISÕESDE

USUÁRIOS

SatisfazMODELO DAREALIDADE

Engenharia Reversa

Modelo da realidadeA partir das visões dos usuários

BASEDE

DADOSPROGRAMAS

O primeiro problema enfrentado no desenvolvimento de aplicações é a obtenção do conhecimento da realidade.

Ninguém dentro da empresa conhece os requerimentos e o alcance da aplicação para desenvolver toda a aplicação. Então, como fazer para obter o conhecimento da realidade de uma forma suficientemente objetiva e detalhada ao mesmo tempo, que nos permita construir um modelo corporativo?

Este conhecimento se encontra em cada uma das visões dos usuários. Cada usuário conhece bem os objetos que trabalha cotidianamente, a informação que ele gerencia, as regras que devem ser seguidas, os cálculos que devem ser realizados.

O ponto de partida da metodologia GeneXus é: descrever as visões dos usuários para modelar o sistema; e a partir da definição da realidade do modelo, o GeneXus constrói o suporte computacional - base de dados e programas - de forma totalmente automática.

Page 4: 93909254 GENEXUS Heuristica Apostila Teorica

4

Desenvolvimento com GeneXus

REALIDADE

DESCRIÇÃODE OBJETOS

Utilizando GeneXus, a tarefa básica do analista é a descrição da realidade. Somente o homem pode desenvolver esta tarefa, já que só ele pode entender o problema do usuário.

O analista GeneXus trabalha em alto nível, em vez de realizar tarefas de baixo nível como: desenhar arquivos, normalizar, desenhar programas, programar, buscar e eliminar os erros dos programas.

Para começar o desenvolvimento de uma aplicação com GeneXus, primeiramente deve ser criado um novo projeto ou base de conhecimento.

Uma vez criada uma nova base de conhecimento (em inglês é: knowledge base; abreviado: KB), o seguinte passo é descrever as visões dos usuários. Para isso, os objetos da realidade (prestando atenção aos substantivos que os usuários mencionam em suas descrições, como por exemplo: clientes, produtos, faturas) e passar a defini-los mediante objetos GeneXus.

Com a definição destes objetos, o GeneXus pode extrair o conhecimento, desenhar a base de dados e os programas da aplicação em forma totalmente automática.

Page 5: 93909254 GENEXUS Heuristica Apostila Teorica

5

Desenvolvimento com GeneXus

REALIDADE

DESCRIÇÃODE OBJETOS

BASE DECONHECIMENTO

Utilizando GeneXus, a tarefa básica do analista é a descrição da realidade. Somente o homem pode desenvolver esta tarefa, já que só ele pode entender o problema do usuário.

O analista GeneXus trabalha em alto nível, em vez de realizar tarefas de baixo nível como: desenhar arquivos, normalizar, desenhar programas, programar, buscar e eliminar os erros dos programas.

Para começar o desenvolvimento de uma aplicação com GeneXus, primeiramente deve ser criado um novo projeto ou base de conhecimento.

Uma vez criada uma nova base de conhecimento (em inglês é: knowledge base; abreviado: KB), o passo seguinte é descrever as visões dos usuários. Para isso, os objetos da realidade (prestando atenção aos substantivos que os usuários mencionam em suas descrições, como por exemplo: clientes, produtos, faturas) e passar a defini-los mediante objetos GeneXus.

Com a definição destes objetos, o GeneXus pode extrair o conhecimento, desenhar a base de dados e os programas da aplicação em forma totalmente automática.

Page 6: 93909254 GENEXUS Heuristica Apostila Teorica

6

REALIDADE

Desenvolvimento com GeneXus

DESCRIÇÃODE OBJETOS

BASEDE

DADOS

PROGRAMAS

BASE DECONHECIMENTO

A partir dos objetos definidos na base de conhecimento, GeneXus gera automaticamentetanto os programas de criação/reorganização da base de dados como os programas da aplicação.

Depois, se um objeto da realidade muda, são identificadas as novas ou diferentes características acerca do mesmo, ou encontrando objetos ainda não modelados. O analista GeneXus deve refletir sobre as mudanças correspondentes nos objetos GeneXus e a ferramenta se encarrega automaticamente de realizar as modificações necessárias tanto na base de dados como nos programas associados.

A metodologia GeneXus é uma metodologia incremental, pois, parte da base da construção de um sistema mediante realizações sucessivas.

Em cada momento, o analista GeneXus define o conhecimento que tem e assim que passa a ter mais conhecimento (ou simplesmente um conhecimento diferente), reflete na base de conhecimento, e o GeneXus se ocupa de fazer automaticamente todas as adaptações na base de dados e nos programas.

Se GeneXus não for capaz de realizar automaticamente as modificações na base de dados e nos programas, conforme sejam realizadas as mudanças que assim o requerem, o desenvolvimento incremental seria inviável

Page 7: 93909254 GENEXUS Heuristica Apostila Teorica

7

Data Providers(DP)

Procedimentos(Procs)

Web Panels(Wbps)

Alguns objetos GeneXus

Transações(Trns)

e tem mais, que veremos...

Uma vez criada uma nova base de conhecimento, o passo seguinte consiste em começar a descrever os objetos da realidade mediante objetos GeneXus.

Os objetos GeneXus mais importantes são:

Transações Permite definir os objetos da realidade que o usuário manipula (ex: clientes, produtos, fornecedores, faturas, etc.). São os primeiros objetos definidos, já que através das transações, GeneXus infere o desenho da base de dados.Além de ter por objetivo a definição da realidade e a conseqüente criação da base de dados normalizada, cada transação tem associada uma janela para ambiente windows e outro para ambiente Web, para permitir ao usuário inserir, eliminar e modificar de forma interativa a base de dados. O analista GeneXus decidirá se trabalha em ambiente windows, Web, ou ambos, e GeneXus gera os programas para isso.

ProcedimentosPermitem recuperar informação da base de dados, e será mostrada na tela, em um arquivo ou impressa em papel. São as típicas listagens ou relatórios. Além disso, permitem atualizar informação da base de dados.

Data ProvidersPermitem carregar e devolver dados hierárquicos para troca de informação entre objetos da mesma aplicação ou de outras aplicações.

Web PanelsPermite ao usuário realizar interativamente consultas na base de dados, através de uma janela. Exemplo: uma web panel permite ao usuário ingressar uma faixa de caracteres, e mostra todos os clientes cujos nomes se encontram dentro dessafaixa.São objetos muito flexíveis que podem ser usados para múltiplos usos. Não permitem a atualização da base de dados, somente consultá-los.

Page 8: 93909254 GENEXUS Heuristica Apostila Teorica

8

Processo de desenvolvimento de umaaplicação com GeneXus

Base de ConhecimentoBase de Conhecimento

BaseBasede de

DadosDados

Data Providers(DP)

Procedimentos(Procs)

Web Panels(Wbps)

Transações(Trns)

Os primeiros objetos definidos são as transações, já que é a partir delas que o GeneXus extrai o conhecimento necessário para desenhar o modelo de dados normalizado (em 3ª. forma normal). Depois vão se definindo os demais objetos que correspondam

Page 9: 93909254 GENEXUS Heuristica Apostila Teorica

9

Criação da Base de Dados

BaseBasede de

DadosDados

Programas CriaçãoBD

Base de ConhecimentoBase de Conhecimento

Data Providers(DP)

Procedimentos(Procs)

Web Panels(Wbps)

Transações(Trns)

GeneXus gera automaticamente os programas necessários para criar a base de dados e os executa. Desta forma a base de dados é criada pelo GeneXus de forma automática.

Page 10: 93909254 GENEXUS Heuristica Apostila Teorica

10

Programas de Aplicação

(Trns, Procs, Wbps, etc)

Geração dos Programas da aplicação

BaseBasede de

DadosDados

Base de ConhecimentoBase de Conhecimento

Data Providers(DP)

Procedimentos(Procs)

Web Panels(Wbps)

Transações(Trns)

Depois, GeneXus gera programas de aplicação para interagir com a base de dados previamente criada.

Page 11: 93909254 GENEXUS Heuristica Apostila Teorica

11

Resultado final na Etapa de Desenvolvimento

BaseBasede de

DadosDados

Base de ConhecimentoBase de Conhecimento

Programas de Aplicação

(Trns, Procs, Wbps, etc.)

Data Providers(DP)

Procedimentos(Procs)

Web Panels(Wbps)

Transações(Trns)

Uma vez criada a base de dados e gerados os programas, contamos com uma aplicação pronta para executar.

Page 12: 93909254 GENEXUS Heuristica Apostila Teorica

12

As visões dos usuários mudam

Nova Nova BaseBasede de

DadosDados

BaseBasede de

DadosDados

Programas de Aplicação

(Trns, Procs, Wbps, DPs)

NovosProcedimentos

NovosData Providers

NovosWeb Panels

NovaNovaBaseBasede de

DadosDados

NovasTransações

Base de ConhecimentoBase de Conhecimento

Durante o ciclo de vida da aplicação, vai surgir repetidamente à necessidade de serem feitas modificações na base de conhecimento, seja porque as visões dos usuários mudaram, ou porque devem ser feitas correções, ou acrescentar novos conhecimentos.

As modificações realizadas na base de conhecimento serão analisadas pelo GeneXus para avaliar a necessidade de efetuar mudanças na base de dados (por exemplo: modificação/criação de tabelas/índices), ou não.

Em caso de detectar mudanças para efetuar na base dados, o GeneXus vai detalhar os mesmos num relatório de análise de impacto (IAR: Impact Analisis Report), é um relatório que explica todas as mudanças sobre tabelas, índices, dados, etc. que precisam ser realizados que refletem a nova realidade.

Mesmo assim, no relatório de análise de impacto, se informam os eventuais problemas que as mudanças em questões podem ocasionar como ter inconsistências ou redundâncias.

Page 13: 93909254 GENEXUS Heuristica Apostila Teorica

13

Análise de Impacto Automático

Análisede

impacto

Nova Nova BaseBasede de

DadosDados

BaseBasede de

DadosDados

Programas de Aplicação

(Trns, Procs, Wbps, DPs)

NovaNovaBaseBasede de

DadosDados

Base de ConhecimentoBase de Conhecimento

NovosProcedimentos

NovosData Providers

NovosWeb Panels

NovasTransações

Algumas vezes a nova base de dados coincide com a anterior. Outras vezes isto não ocorre, e a base de dados sofre alguma modificação para representar a nova realidade.

O analista deve estudar o relatório de análise de impacto e resolver se deseja realizar efetivamente as mudanças na base de dados, ou renunciar a base de dados e deixar como estava, ou fazer outras alterações.

Page 14: 93909254 GENEXUS Heuristica Apostila Teorica

14

Geração de Programas de Reorganização da Base de Dados

Programasde

Reorganiz.

Programas de Aplicação

(Trns, Procs, Wbps, DPs)Nova Nova BaseBasede de

DadosDados

BaseBasede de

DadosDados

NovaNovaBaseBasede de

DadosDados

Base de ConhecimentoBase de Conhecimento

NovosProcedimentos

NovosData Providers

NovosWeb Panels

NovasTransações

Se o analista opta por aplicar as mudanças propostas, dizemos que optou por reorganizar a base de dados. Utilizamos este termo para definir a ação de aplicar mudanças físicas sobre a base de dados.

GeneXus gera os programas que implementam as modificações sobre as estruturas físicas da base de dados, e mediante sua execução nos brindará com uma nova versão da base de dados com as mudanças efetuadas.

Page 15: 93909254 GENEXUS Heuristica Apostila Teorica

15

Análise automática do impactodas mudanças sobre os programas

Análisede Impacto sobre os programas

Novos Programas de Aplicação

(Trns, Procs, Wbps, DPs)

NovaNovaBaseBasede de

DadosDados

Base de ConhecimentoBase de Conhecimento

NovosProcedimentos

NovosData Providers

NovosWeb Panels

NovasTransações

Visto que se quer reorganizar a base de dados ou não, considerando as novas definições introduzidas, GeneXus estuda o impacto das alterações sobre os programas atuais.

Page 16: 93909254 GENEXUS Heuristica Apostila Teorica

16

Geração automática de novos programas

NovaNovaBaseBasede de

DadosDados

Novos Programas de Aplicação

(Trns, Procs, Wbps, etc.)

Geração de

programas

Base de ConhecimentoBase de Conhecimento

NovosProcedimentos

NovosData Providers

NovosWeb Panels

NovasTransações

Por último, GeneXus prossegue com a geração/regeração dos programas de aplicaçãonecessários, obtendo assim uma nova versão da aplicação.

Page 17: 93909254 GENEXUS Heuristica Apostila Teorica

17

Nova realidade, com as mudanças na aplicação

NovaNovaBaseBasede de

DadosDados

Novos Programas de Aplicação

Base de ConhecimentoBase de Conhecimento

NovosProcedimentos

NovosData Providers

NovosWeb Panels

NovasTransações

Assim novamente teremos uma aplicação pronta para executar, com as mudanças aplicadas.

Page 18: 93909254 GENEXUS Heuristica Apostila Teorica

18

• O Lugar onde se armazena a informação para gerar a aplicação em certa plataforma de execução se chama Environment.

• O uso de vários Environments permite diferentes implementações da mesma aplicação.

C# & SQL Server

C# & MySQL

Java & MySQL

GeneXusProject

Knowledge Base

Environments:

Implementation #1

Implementation #2

C# Application

MySQL

C# Application

SQL

Implementation #3Java Application

MySQL

Environments

Page 19: 93909254 GENEXUS Heuristica Apostila Teorica

19

• Quando se cria uma base de conhecimento (KB), GeneXus pede ao usuário que selecione o Environment que vai trabalhar:

• Com estes dados, se cria automaticamente um ‘Environment’.

Environments

Para criar uma base de conhecimento, selecionar na barra do menu do GeneXus, o item File / New Knowledge Base. Em seguida vai aparecer um diálogo como o que segue:

Deverá ser indicado;

• Nome da Knowledge Base: em nosso caso será BillingSystem.• Diretório onde será criada.• O ‘Environment’ por default: veja que são mostradas linguagens de programação. GeneXus os utilizará para criar os programas associados a base de dados. As opções oferecidas são: C# Environment, Java Environment e Ruby Environment.• Language: Idioma em que vai aparecer os botões, mensagens, etc.

No momento de criar a KB se começa a definir o ambiente de implementação (Environment) cujas definições serão depois completadas no momento de executar a aplicação (nome da base de dados, servidor, forma de conexão, etc).

Page 20: 93909254 GENEXUS Heuristica Apostila Teorica

20

• Para ver o ‘Environment’ criado, selecionamos a janela de Preferences do Knowledge Base Navigator:

Default Environment

Environments

Page 21: 93909254 GENEXUS Heuristica Apostila Teorica

21

Environments• Para ter implementações em diferentes plataformas, criamos

vários ‘Environments’.

Page 22: 93909254 GENEXUS Heuristica Apostila Teorica

22

• Vemos os ‘Environments’ criados:

Environments

C# & SQL Server

Java & MySQL

GeneXusProject

Knowledge Base

Environments:

O environment ativo é indicado em negro e tem o icone de “Play”.

Page 23: 93909254 GENEXUS Heuristica Apostila Teorica

23

Construir uma aplicação mediante aproximações sucessivas.

DEFINIÇÃO INICIAL

Metodologia Incremental

A construção automática da base de dados e programas permite ao GeneXus aplicar esta metodologia de desenvolvimento, conhecida como metodologia incremental.

Como explicado anteriormente, este processo é realizado mediante aproximações sucessivas.

Page 24: 93909254 GENEXUS Heuristica Apostila Teorica

24

Metodologia Incremental

Aplicar um desenvolvimento incremental, pode gerenciar diferentes versões da aplicação.

• Versão para prototipação

• Versão para colocar em produção

Referente a versões (do que se trata, como realizar, etc.) voltaremos no final. No momento ésuficiente saber que ao criar a base de conhecimento, os programas que estaremos executando, programas reais, serão uma versão da aplicação, de teste. Uma vez que resolvermos que essa versão está pronta para ser colocada em produção, basta fazer outra ‘versão’ da aplicação, e pronto!.

Page 25: 93909254 GENEXUS Heuristica Apostila Teorica

25

Vantagens da Prototipação

• Permite ver resultados no início

• Permite seguir os requerimentos do usuário

• Detecta os erros no início

• O usuário se compromete com o desenvolvimento

• Sistemas de melhor qualidade

Toda comunicação é susceptível a erros:

• O usuário esquece certos detalhes• O analista não toma nota de alguns elementos• O usuário se equivoca em algumas situações• O analista interpreta mal algumas explicações do usuário

Como a implementação dos sistemas é habitualmente uma tarefa que consome bastante tempo. E muitos destes problemas somente são detectados nos testes finais do sistema, o custo em tempo e dinheiro em solucioná-los é muito grande. Sabendo que a realidade não permanece estática, por isto não é razoável pensar que as especificações não vão mudar até que o sistema seja implementado. A conseqüência de manter as especificações, é que se acaba implementando uma solução relativamente insatisfatória.

O impacto destes problemas diminui muito se for possível testar cada especificação, imediatamente, e saber qual é a repercussão de cada alteração sobre o resto do sistema. Uma primeira aproximação de resolução deste problema, oferecida por diversos sistemas, é a possibilidade de mostrar ao usuário formatos de janelas, relatórios, etc. animados por menus. Isto permite ajudar o usuário a ter uma idéia de como o sistema será construído, porém no final, sempre aparecem surpresas.

Uma situação bastante diferente seria colocar a disposição do usuário, para sua execução imediata, uma aplicação funcionalmente equivalente à desenhada, até nos mínimos detalhes. Isto é o que faz o GeneXus: um protótipo GeneXus é uma aplicação pronta, funcionalmente equivalente a aplicação de produção.

Assim a aplicação pode ser totalmente provada antes de colocar em produção, e durante estes testes, o usuário afinal pode trabalhar com os dados reais, testando de uma forma natural não somente os formatos de telas, relatórios, etc., mas também suas fórmulas, regras do negócio, estruturas de dados, etc. e trabalhar com seus dados reais.

Isto somente é possível graças a construção automática que o GeneXus realiza do suporte computacional (base de dados e programas).

Page 26: 93909254 GENEXUS Heuristica Apostila Teorica

26

Objeto Transação

A análise de toda aplicação GeneXus começa com o desenho das transações.

As transações permitem definir os objetos da realidade.

Para identificar quais são as transações que precisam ser criadas, se recomenda prestar atenção aos substantivos que o usuário menciona quando escreve a realidade.

Além de ter por objetivo a definição da realidade a conseqüente criação da base de dados normalizada, as transações, igual como os demais objetos GeneXus, provocam a geração de programas. Os programas oriundos das transações têm o objetivo de permitir inserir, eliminar e modificar de forma interativa nas tabelas que tenham implicações, controlando estes programas e a integridade referencial dosdados.

Page 27: 93909254 GENEXUS Heuristica Apostila Teorica

27

TransaçõesGeneralidades

Definição Objeto a partir do qual GeneXus criará de forma automática a base de dados na 3ª forma normal

• Descrevem as visões dos usuários.

• Contem toda a informação necessária referente os dados da aplicação e de como os usuários acessam o sistema para sua manipulação (inserir, modificar e eliminar).

Elementos que as compõem:

Alguns elementos das transações, que serão vistos:Estrutura: Permite definir os atributos (campos) que compõem a transação e a reação entre elas. A partir deles, o GeneXus conclui o desenho da base de dados: tabelas, chaves, índices, etc.Web Form: Cada transação contém um Form (tela) Web mediante o qual se realiza inserções, eliminações e alterações no ambiente Web.Regras: As regras permitem definir o comportamento particular das transações. Por exemplo, permitem definir valores por default para os atributos, definir validações sobre os dados, etc.Eventos: As transações suportam a programação orientada a eventos. Este tipo de programação permite definir código ocioso, que se ativa em resposta a certas ações provocadas pelo usuário ou pelo sistema.

Variáveis: Permite a definição de variáveis que são locais a Transação.

Propriedades: Permitem definir certos detalhes referentes ao comportamento da transação.

Documentação: Permite a inclusão de texto técnico, para ser utilizado como documentação do sistema.

Ajuda: Permite a inclusão de texto de ajuda, para ser consultado pelos usuários em tempo de execução da transação.

Category e Work With: Patterns (padrões) que podem ser aplicados a Transação com a finalidade de implementar de forma automática certa funcionalidade.

Alguns destes elementos também estão associados a outros tipos de objetos GeneXus.

Page 28: 93909254 GENEXUS Heuristica Apostila Teorica

28

Exemplo: Precisa registrar informação de fornecedores.

Definir a transação “Supplier”, com estrutura:

{SupplierId* Identificador de fornecedorSupplierName Nome de fornecedorSupplierAddress Endereço de fornecedorSupplierPhone Telefone de fornecedor

}

TransaçõesEstrutura

A estrutura de uma transação permite definir que atributos integram a mesma e como estão relacionados.

Por exemplo, se numa aplicação é necessário registrar informação de fornecedores, terá que ser definido uma transação, a qual podemos dar o nome “Supplier” e sua estrutura pode ser a seguinte:

{SupplierId*SupplierNameSupplierAddressSupplierPhone }

Esta lista de nomes (um dos quais está sucedido do símbolo asterisco) corresponde aos atributos dos fornecedores que interessam ser mantidos.

Então, criamos uma transação de nome “Supplier” cuja estrutura é composta dos atributos SupplierId*, SupplierName, SupplierAddress e SupplierPhone.

Isto significa que cada fornecedor é identificado por um código SupplierId (o qual fica determinado pelo asterisco após o atributo¹), terá um nome SupplierName, um endereço SupplierAddress e um telefone SupplierPhone.

Para cada atributo definido na estrutura, deveremos indicar coisas como seu tipo de dados, descrição e alguns outros detalhes mais que veremos.

_____________________________________________________________________________

1 O asterisco corresponde a uma notação teórica que utilizamos para indicar que o atributo é identificador. Como veremos, esse asterisco em GeneXus aparece representado por um ícone de chave e o usuário pode configurá-lo mediante um menu contextual que oferece esta possibilidade.

Page 29: 93909254 GENEXUS Heuristica Apostila Teorica

29

Estrutura em GeneXus:

TransaçõesEstrutura

Atributos ChaveNa página anterior foi explicado que o asterisco após o atributo SupplierId indica que o mesmo é o identificador na transação. Toda transação deve ter pelo menos um identificador, isto é, um atributo ou conjunto de atributos que definam a unicidade da informação.

No exemplo não vão existir dois fornecedores com o mesmo valor de SupplierId. Em definitivo se trata do conceito de chave primária, e para fazer a escolha dos atributos que a compõem, devemos levar em consideração os requisitos da realidade do objeto.

Nos casos em que não se pode determinar um identificador, deve-se optar por criar um atributo artificial (não existente na realidade), e que seu valor seja atribuído internamente, por exemplo, na forma correlativa.

Como pode ser observado no editor de transações GeneXus, um ícone de chave representa o asterisco que usamos como notação teórica.

Atributo “descriptor”O ícone com uma lupa representa o atributo que melhor descreve a transação. Em outras palavras seriam os atributos que tem maior carga semântica na transação.

Por default o primeiro atributo na estrutura da transação que seja do tipo de dados character, se define como “atributo descriptor”. É possível definir outro atributo como descriptor utilizando o menu pop-up correspondente, assim como não definir nenhum.

Page 30: 93909254 GENEXUS Heuristica Apostila Teorica

30

Exemplo: Precisa registrar informação referente a fatura de venda.

TransaçõesEstrutura

Invoice{InvoiceId* Identificador de faturaInvoiceDate Data de faturaCustomerId Identificador de clienteCustomerName Nome de cliente

Detail{ProductId* Identificador de produtoProductDescription Descrição de produtoProductPrice Preço de produtoInvoiceDetailQuantity Quantidade de produto levada da linhaInvoiceDetailAmount Valor da linha de fatura

}InvoiceAmount Valor total da fatura

}

Níveis de uma transaçãoA transação “Invoice” consta de dois níveis: o primeiro nível fica implícito, não necessitando de um jogo de chaves; e o segundo nível corresponde ao conjunto de atributos que ficam definidos entre chaves ¹.O fato de definir um segundo nível significa que existem várias instâncias do mesmo, para cada instancia do nível anterior. No exemplo, um cabeçalho da fatura e seus vários produtos.Cada nível de uma transação define um grupo de atributos que devem operar em conjunto, ouseja, se insere, elimina ou se altere conjuntamente na base de dados.

Chamamos de transação plana a uma transação de um nível só. Assim, podemos dizer que a transação “Supplier” é a transação plana.A diferença da transação “Invoice” que contém dois níveis. É comum falarmos de “cabeçalho”para o primeiro nível e de “linhas” para o segundo.

Para cada nível da transação, deve ser indicado quais atributos atuam como identificador. O identificador de cada nível pode ser composto somente de um atributo, como é o caso das transações que vimos até agora, ou pode ser composto por vários atributos.

Na transação “Invoice” o atributo InvoiceId é o identificador do primeiro nível, e o atributo ProductId + o atributo dos níveis superiores é o identificador do segundo nível. Este último significa que para um número de fatura dado, não é repetido o valor do atributo ProductId em distintas linhas.

Uma transação pode conter vários níveis paralelos, assim como aninhados.____________________________________________________________________________

1 O asterisco é uma notação teórica representando que o atributo que o antecede é identificador na transação, o jogo de chaves também é utilizado como notação teórica, para representar que os atributos contidos formam parte de um nível aninhado, e que tem uma representação visual em GeneXus distinta, mas indica o mesmo.

Page 31: 93909254 GENEXUS Heuristica Apostila Teorica

31

Estrutura em GeneXus

TransaçõesEstrutura

Em GeneXus fica visualmente claro o nível correspondente as linhas da fatura.A cada nível de uma transação se deve atribuir um nome, tipo1 e descrição (exceto ao primeiro nível, que recebe como nome o da transação).

Níveis paralelos e aninhadosUma transação pode ter vários níveis aninhados, assim como níveis paralelos.Por exemplo, no caso hipotético que uma fatura pode ter vários pagamentos, poderíamos definir dois tipos de estrutura, dependendo do que se quer representar:

Invoice { Invoice {InvoiceId* InvoiceId*

InvoiceDate InvoiceDateCustomerId CustomerIdCustomerName CustomerNameInvoiceAmount InvoiceAmount

Detail Detail{ProductId* {ProductId*ProductDescription ProductDescriptionProductPrice ProductPriceInvoiceDetailQuantity InvoiceDetailQuantityInvoiceDetailAmount} InvoiceDetailAmountPayment Payment

{InvoicePaymentDate* {InvoicePaymentDate*InvoicePaymentAmount} InvoicePaymentAmount}}

} } Na estrutura da esquerda é definido uma fatura que tem muitos produtos e muitos pagamentos, mas não tem relação direta entre os produtos e os pagamentos (a não ser pelo fato de pertencerem à mesma fatura). Na estrutura da direita são registrados os pagamentos por produto comprado. É fácil compreender que o segundo e o terceiro nível da transação da esquerda são paralelos. Ambos estão aninhados ao primeiro nível, mas entre eles, são paralelos. Na estrutura da direita, são todos os níveis aninhados.

________________________________________________________________________________________

1 Como veremos depois, o tipo que se define para um nível de uma transação, será utilizada para trabalhar com business components, conceito relacionada as transações.

Page 32: 93909254 GENEXUS Heuristica Apostila Teorica

32

Invoice{

InvoiceId*InvoiceDateCustomerIdCustomerName

Detail{ ProductId*ProductDescriptionProductPriceInvoiceDetailQuantityInvoiceDetailAmount

}InvoiceAmount

}

Definição do modelo de dados: estruturas das transações

TransaçãoTransação

Supplier{SupplierId*SupplierNameSupplierAddressSupplierPhone

}

TabelaSUPPLIER

SupplierId*SupplierNameSupplierAddressSupplierPhone

Transações

InvoiceId*ProductId*ProductDescriptionProductPriceInvoiceDetailQuantityInvoiceDetailAmount

TabelaINVOICEDETAIL

InvoiceId*InvoiceDateCustomerIdCustomerNameInvoiceAmount

TabelaINVOICE

GeneXus utiliza a estrutura das transações para capturar o conhecimento necessário para definir automaticamente qual é o modelo de dados que será criado.

Para poder realizar a normalização da base de dados ser realizada numa 3ª forma normal, GeneXus deve extrair as dependências funcionais existentes entre os atributos definidos na base de conhecimento.

Na base de conhecimento de nosso exemplo, temos definido na transação “Supplier” e de sua estrutura GeneXus extraímos as seguintes dependências funcionais:

SupplierId � {SupplierName, SupplierAddress, SupplierPhone}

Dadas estas dependências funcionais, GeneXus determina que deve criar uma tabela que terápor default o mesmo da transação (SUPPLIER)1, e que estará conforme nem mais nem menos que pelos quatro atributos anteriores, sendo SupplierId a chave primária da mesma:

Diremos que a transação “Supplier” tem a tabela associada SUPPLIER quando inserir, modificar ou eliminar pela transação, assim estarão armazenando, modificando ou eliminando fisicamente na tabela associada.

_____________________________________________________________________

1 Na documentação, para distinguir o nome de uma tabela do nome de uma transação escreveremos o nome da tabela em maiúsculo.

SUPPLIER SupplierId SupplierName SupplierAddress SupplierPhone

Page 33: 93909254 GENEXUS Heuristica Apostila Teorica

33

A partir da estrutura da transação “Invoice”, GeneXus determina que deve criar duas tabelas:

Tabela INVOICE, correspondente ao primeiro nível da transação:

Chave primária: InvoiceId

Tabela INVOICEDETAIL correspondente ao segundo nível da transação:

Chave primária: {InvoiceId, ProductId}Chave estrangeira: InvoiceId

já que as dependências funcionais são:

InvoiceId � {CustomerId, CustomerName, InvoiceDate, InvoiceAmount}

{InvoiceId, ProductId} � {ProductDescription, ProductPrice, InvoiceDetailQuantity,

InvoiceDetailAmount}

Observe que a chave primária da tabela INVOICEDETAIL é a concatenação do identificador do primeiro nível, InvoiceId, com o identificador do segundo nível, ProductId. A regra é geral: a chave primária da tabela correspondente a um nível n de uma transação se obtêm em concatenar os identificadores dos n-1 níveis anteriores aninhados, com o identificador desse nível.

GeneXus atribuiu um nome pré-determinado às tabelas que cria. A tabela associada ao primeiro nível de uma transação atribui o mesmo nome que o da transação; e as tabelas dos níveis subordinados são atribuídas a concatenação dos nomes dos níveis. Por isso é que a tabela associada ao segundo nível da transação “Invoice” recebe o nome de INVOICEDETAIL, sendo que o nome do primeiro nível é o da transação INVOICE, e o segundo nível é DETAIL. Os nomes das tabelas podem ser modificados pelo analista GeneXus quando o desejar.

INVOICE InvoiceId CustomerId CustomerName InvoiceDate InvoiceAmount

INVOICEDETAIL InvoiceId ProductId ProductDescription ProductPrice

InvoiceDetailQuantity InvoiceDetailAmount

Page 34: 93909254 GENEXUS Heuristica Apostila Teorica

34

Customer{CustomerId*CustomerNameCustomerAddressCustomerGender

}

Ao definir as novas transações:

Product{ProductId*ProductDescriptionProductPriceProductStock

}Sexo do cliente

TransaçõesEstrutura

Depois de ter modelado a transação “Invoice”, damos conta que existem informações de clientes e produtos que é interessante manter independente das faturas. Isto é, os clientes e os produtos são dois objetos de realidades independentes das faturas, para isso é necessário criar duas novas transações "Customer" e "Product" detalhadas acima.

Dependências funcionaisCom estas novas transações definidas, aparecem novas dependências funcionais:

CustomerId � {CustomerName, CustomerAddress, CustomerGender, CustomerStatus}

ProductId � {ProductDescription, ProductPrice, ProductStock}

Que conduzem diretamente a criação de duas novas tabelas:

Chave primária: CustomerId

E:

Chave primária: ProductId

CUSTOMER CustomerId CustomerName CustomerAddress CustomerGender

PRODUCT ProductId ProductDescription ProductPrice ProductStock

Page 35: 93909254 GENEXUS Heuristica Apostila Teorica

35

InvoiceId*InvoiceDateCustomerIdCustomerNameInvoiceAmount

TabelaINVOICE

InvoiceId*ProductId*ProductDescriptionProductPriceInvoiceDetailQuantityInvoiceDetailAmount

TabelaINVOICEDETAIL

TabelaSUPPLIER

SupplierId*SupplierNameSupplierAddressSupplierPhone

Tabela CUSTOMER

CustomerId*CustomerNameCustomerAddressCustomerGender

Tabela PRODUCT

ProductId*ProductDescriptionProductPriceProductStock

TransaçõesNormalização: alterações nas tabelas

O conjunto total de dependências funcionais existentes requer algumas modificações nas tabelas INVOICE e INVOICEDETAIL desenhadas previamente para que o desenho da base de dados permaneça na 3ª forma normal1.Se representarmos sobre as tabelas CUSTOMER e INVOICE as dependências funcionais encontradas para os seus atributos:

Podemos ver claramente que INVOICE viola a 3ª forma normal (existe uma dependência funcional transitiva):

InvoiceId � CustomerId

CustomerId � CustomerName

InvoiceId � CustomerName

por tanto GeneXus normaliza, tirando o atributo CustomerName da tabela INVOICE:

Agora CustomerName somente estará na tabela CUSTOMER.

_______________________________________________________________________________

1 Para mais informação sobre as formas normais (3ª forma normal, etc.) recomendamos a leitura do documento “Fundamentos de bases de dados relacionais”, que está incluído no capítulo “Anexos” do curso GeneXus não presencial. Do contrário, pode pedir ao docente.

Page 36: 93909254 GENEXUS Heuristica Apostila Teorica

36

Agora veremos as dependências funcionais encontradas nas tabelas PRODUCT e INVOICEDETAIL:

podemos perceber claramente que a tabela INVOICEDETAIL está violando a 3ª forma normal (existem atributos que dependem de forma parcial da chave primária):

ProductId � ProductDescription ProductId � ProductPrice

{InvoiceId, ProductId} � ProductDescription {InvoiceId, ProductId} � ProductPrice

Portanto GeneXus normaliza, tirando os atributos ProductDescription e ProductPrice da tabela INVOICEDETAIL:

ProductDescription e ProductPrice somente ficarão na tabela PRODUCT.

Page 37: 93909254 GENEXUS Heuristica Apostila Teorica

37

Transações

• Conceitos iguais devem ter o mesmo nome

• Conceitos diferentes NÃO devem ter o mesmo nome

Invoice {

InvoiceId*CustomerIdCustomerName...

}

Customer{

CustomerId*CustomerName

}

Invoice {

InvoiceId*InvoiceCustomerId...

}

Customer{

CustomerId*CustomerName

}

Invoice {

InvoiceId*DateCustomerIdCustomerName...

}

VendorInvoice{

VendorInvoiceId*DateSupplierId*SupplierName...

}

incorreto

Relações: estabelecidas pelos nomes de atributos

Conceitos iguais devem ter o mesmo nome e conceitos diferentes devem ter nomes diferentes. O GeneXus estabelece as relações através dos nomes dos atributos, de modo que, quando encontra atributos com o mesmo nome em diferentes transações, entende que trata-se do mesmo conceito, e mediante este conhecimento é que pode normalizar.

No exemplo que estamos utilizando, quando o GeneXus encontra o atributo de nome CustomerId tanto na transação "Customer" como na transação "Invoice", analisa que: o atributo tem o mesmo nome em ambas transações, assim possuem o mesmo conceito. Na transação "Customer" CustomerId está marcado como identificador, o qual significa que échave primária na tabela física CUSTOMER; então na tabela física INVOICE será chave estrangeira.

O atributo CustomerName, por sua parte, também se encontra tanto na transação "Customer" como na transação “Invoice”, mas a diferença de CustomerId, não está marcado como identificador em nenhuma transação do modelo; com isso, o GeneXus entende que trata-se de um atributo secundário. As dependências funcionais indicam que o CustomerName o determina CustomerId:

InvoiceId � CustomerIdCustomerId � CustomerName

assim que o GeneXus incluirá a CustomerName na tabela física CUSTOMER (e não na tabela física INVOICE).

Atributos primários e secundáriosUm atributo se qualifica como primário quando o mesmo é identificador em alguma transação do modelo. No exemplo que estamos vendo, CustomerId é um atributo primário, jáque é identificador na transação "Customer".

CustomerName, na verdade é um atributo secundário já que não é identificador em nenhuma transação do modelo.

Page 38: 93909254 GENEXUS Heuristica Apostila Teorica

38

Atributos Armazenados e InferidosAo definir as transações "Customer" e "Product", incluímos nelas certos atributos que não eliminados da transação “Invoice”. Os atributos CustomerId e ProductId, serão incluídos nas transações "Customer" e "Product" respectivamente, e ao serem marcados como identificadores das mesmas, passarão a serem atributos primários. O atributo CustomerName, por sua vez, se agregou na transação "Customer"; e os atributos ProductDescription e ProductPrice na transação "Product". Estes são atributos secundários.Todos os atributos antes mencionados estão em mais de uma transação: partindo do princípio que continuam na transação “Invoice” tal como foi definido no princípio, e foram incluídos nas transações "Customer" e "Product" respectivamente, porque notamos a necessidade de criar estes objetos.Posteriormente, apresentamos 3 estruturas das transações em questão, para poder visualizá-las juntas:

Provavelmente você está se perguntando qual a razão dos atributos secundários CustomerName, ProductDescription e ProductPrice continuam na estrutura da transação "Invoice". A explicação é a seguinte: as estruturas das transações, não são equivalentes às estruturas de tabelas físicas. Nas estruturas das transações podem ser incluídos atributos que não estarão nas tabelas físicas associadas às mesmas, já que na hora de reorganizar a base de dados, o GeneXus analisa o conjunto total de dependências funcionais existentes na base de conhecimento, e cria - ou modifica, segundo o caso - as tabelas físicas, deixando-as na 3ª forma normal.Agora, com que finalidade temos deixado os atributos secundários CustomerName,

ProductDescription e ProductPrice na estrutura da transação “Invoice”? Foram deixados para poder incluí-los em algum dos elementos do objeto da transação, por exemplo, nos forms (GUI-Windows e/ou Web) associados a transação “Invoice”, e assim poder visualizar os valores destes atributos em tempo de execução. Ditos atributos, como temos explicado, não ficam armazenados na tabela INVOICE, nem na tabela INVOICEDETAIL; por exemplo, em tempo de execução quando o usuário ingressa através de algum dos forms (GUI-Windows e/ou Web) um valor de CustomerId (atributo que armazenará na tabela INVOICE sendo chave estrangeira), a continuação mostraráCustomerName correspondente. Dizemos que o atributo CustomerName é um atributo inferido na transação "Invoice", já que seu valor não está armazenado em nenhuma das tabelas associadas a mesma, mas sim que se infere – isto é, se obtêm - da tabela CUSTOMER, dado o valor do atributo CustomerId.

Analogamente, os atributos ProductDescription e ProductPrice também são inferidos na transação “Invoice”, já que não se encontram armazenados nas tabelas associadas àmesma, mas sim que seus valores se inferem na tabela PRODUCT, para serem mostrados na tela.

Invoice{

InvoiceId*InvoiceDate

CustomerIdCustomerName

Detail{ ProductId*

ProductDescriptionProductPrice

InvoiceDetailQuantityInvoiceDetailAmount

}InvoiceAmount

}

Customer{

CustomerId*CustomerName

CustomerAddressCustomerGender

}

Product{

ProductId*ProductDescription

ProductPrice

ProductStock }

Page 39: 93909254 GENEXUS Heuristica Apostila Teorica

39

É conveniente usar padrões para os nomes dos atributos.

• Facilitam a tarefa de dar nome.

• Facilitam a tarefa de integração de bases de conhecimento.

• Facilitam a leitura do código gerado.

TransaçõesEstrutura

Page 40: 93909254 GENEXUS Heuristica Apostila Teorica

40

Nome de atributos: Nomenclatura GIK

Componente de Entidade + Categoria Componente de Entidade + Categoria

[+ Qualificador + Complemento][+ Qualificador + Complemento]

…e em inglês:

TransaçõesEstrutura

Entity Component Qualifier Category

Customer Id

Customer Name

Customer Start Date

Customer End Date

Invoice Id

Invoice Due Date

InvoiceDetail Amount

VendorInvoice id

Entity Component Category Qualifier

Cliente Id

Cliente Nome

Cliente Data Inicial

Cliente Data Final

Fatura Id

Fatura Data Vencimento

FaturaDetalhe Quantidade

FaturaCompra Id

A ARTech definiu um padrão para a nomenclatura de atributos: o GeneXus Incremental Knowledge Base (GIK) que é utilizado pela comunidade de usuários GeneXus.

Nesta nomenclatura, o nome de um atributo se forma com 4 componentes (alguns opcionais, assinalados entre parênteses retos):

Componente de Entidade + Categoria [+ Qualificador + Complemento] 1

Posteriormente descrevemos em que consiste cada componente:

Componente de Entidade (ou Objeto): uma Entidade é um ator (ex: Customer), o objeto evento (ex: VendorInvoice, Fatura de Venda) que intervêm em uma dada aplicação, representado por uma transação GeneXus². Um Componente de Entidade representa qualquer nível subordinado ou paralelo que defina a entidade.

Exemplo: A fatura tem os seguintes componentes, Invoice (cabeçalho), InvoiceLine (linhas da fatura). Se sugere um tamanho de 10 caracteres para representar o componente da Entidade.

Categoria: É a Categoria semântica do atributo que define o rol que o mesmo assume dentro do objeto e dentro do ambiente da aplicação. Sugere que não ultrapasse os 10 caracteres.

Exemplos: Id (identificador), Code (código), Name (nome), Date (data), Description (descrição), Price (preço), Stock (estoque).

_____________________________________________________________________________

1 Para países que utilizem línguas nas quais os adjetivos são colocados depois do substantivo. Em inglês é ao contrário, por isso a categoria (ou substantivo) vai no final.2 Ou um conjunto de Transações paralelas e/ou subordinadas, que falaremos mais adiante.

Page 41: 93909254 GENEXUS Heuristica Apostila Teorica

41

Qualificador: É qualquer adjetivo ou advérbio, entorno de 10 caracteres, que agregue diferenciação conceitual ao nome do atributo para que o torne único.Em geral refere ao texto que qualifica a categoria: Data de Vencimento.Exemplos: Start (inicial), End (final), Due (vencimento)

Complemento: Texto livre até completar a quantidade de caracteres significativos (30) para onome.

No slide se mostram alguns exemplos de nomes de atributos.

Nota 1: As letras maiúsculas permitem estabelecer fronteiras entre os componentes que formam os nomes dos atributos.

Nota 2: Para cada componente se podem utilizar a quantidade de caracteres desejada, ainda se sugere utilizar 10 e que o nome completo não seja superior a 30.

Page 42: 93909254 GENEXUS Heuristica Apostila Teorica

42

Demo

�Uma vez criada a base de conhecimento: criação das primeiras transações

Uma vez criada a base de conhecimento, a mesma ficará aberta para começar a criar as transações.

A criação de objetos, se realiza pressionando Ctrl+N. Os objetos criados ficarão ou na pasta Objects que se pode ver no Folder View da janela KB Navigator.Se desejar que o objeto ao ser criado fique guardado em outra pasta, se deve posicionar em dita pasta e depois fazer click com o botão direito do mouse. No menu escolher New, Object.Também poderá ser indicado a pasta no quadro de criação de um objeto como se vê na imagem.

É mostrado um diálogo onde se deve escolher o tipo de objeto que se deseja criar (neste caso o tipo de objeto: transação), dar um nome ao objeto que se está criando (por exemplo: “Customer”), uma descrição longa, e a pasta na qual guardar o objeto:

Uma vez criada a transação, a mesma ficará aberta para que se defina sua estrutura.

Page 43: 93909254 GENEXUS Heuristica Apostila Teorica

43

TransaçõesDefinição de atributos

F4

Para definir um atributo, simplesmente deve-se digitar no primeiro campo de uma linha (ou ramo) da estrutura, o nome do atributo que se deseja criar. Mediante a tecla de tabulação pode-se passar aos seguintes campos para indicar o tipo de dados do atributo, assim como sua descrição, e no caso que o mesmo venha a ser uma fórmula (conceito que veremos em breve), como calculá-la. Com a tecla Enter pode-se passar a seguinte linha, para definir outro atributo.

Uma vez definidos os atributos na estrutura da transação, somente restará guardar/salvar as mudanças.

Caso necessite modificar o nome de um atributo, seu tipo de dados, descrição, nulabilidade, ou fórmula, bastará dar um duplo clique sobre o campo desejado, e o mesmo é habilitado e pode ser editado. Após as alterações as mudanças precisam ser salvas novamente.

Para indicar que um ou mais atributos são identificadores na transação, deve-se selecioná-los e pressionar CTRL+K; aparecerão com um símbolo de chaves.

Para definir o início de outro nível na transação, deve-se digitar CTRL+L, e automaticamente se produz uma endentação e o usuário deverá dar um nome a esse nível, assim, como definir o nome de seu tipo de dado¹ e uma descrição para o nível.

Para indicar que um atributo de um dos níveis da transação será o atributo “descriptor”, deve-se selecioná-lo e clicar CTRL +D.

GeneXus conta com menus pop-up², que são menus que se abrem quando o usuário está posicionado em determinado contexto e fazendo click com botão direito do mouse. Por exemplo, ao clicar com o botão direito do mouse sobre um atributo da estrutura, abre-se um menu pop-up sobre o atributo selecionado, que oferece varias utilidades, como por exemplo indicar que o atributo é chave (opção “Toggle key”), tira-lo da estrutura, passá-lo a um seguinte nível de animação, etc.

Cada atributo contém propriedades. Algumas delas (as fundamentais e obrigatórias) são as que se oferecem diretamente na estrutura para seu ingresso “inline”. Para acessar o diálogo que permite configurar todas as propriedades de um atributo, deve-se selecionar o item Properties do menu contextual, ou pressionando a tecla F4. Na figura alteramos a propriedade Autonumber que como veremos oportunamente, permite autonumerar atributos chave primária.

_______________________________________________________________________________________

1 Veremos sua utilidade enquanto estudarmos os “business components”.2 Também chamados “contextuais” visto que variam segundo o contexto.

Page 44: 93909254 GENEXUS Heuristica Apostila Teorica

44

Name: É o nome do atributo. Utilizado para identificá-lo.

Description: A “Descrição” ou mais propriamente “Nome extenso” é uma definição ampliada do atributo. O atributo deve ser bem identificável com essa descrição, com independência do contexto, e principalmente deve ser entendível pelo usuário final. Deve ser um identificador global do atributo, isto é, não se deve atribuir dois atributos na base de conhecimento com a mesma descrição, já que será através desta descrição que o usuário final poderá selecionar atributos para definir suas próprias consultas na base de dados, com o GXQuery, executando “relatórios dinâmicos” (tema bastante simples, mas que não será abordado neste curso).

Relacionadas a esta propriedade, estão às propriedades Title, Column Title e Contextual Title. As 2 primeiras por default tem o mesmo valor especificado no Description, podendo ser modificado.

Title: A descrição aqui inserida é colocada por default ao lado do atributo, cada vez que se utilize em saídas “planas” como, por exemplo: no primeiro nível dos forms das transações (veremos em breve os forms).

Column Title: A descrição aqui inserida é por default como o título do atributo, cada vez que for incluído na coluna de um grid. (no caso de uma transação somente se trata de um atributo inferido, como por exemplo o atributo ProductDescription na transação Invoice)1.

Contextual Title: Quando o atributo pertence ao segundo nível de uma transação, e não é inferido (exemplo InvoiceDetailQuantity em Invoice), o nome da coluna do grid da transação pega desta propriedade. Observe que por default se pega da propriedade Description, mas tirando o nome da transação, pois assume o contexto.

Type DefinitionBased on: Permite associar um domínio ao atributo. Ao atribuir um domínio a um atributo,

certas propriedades do atributo são desabilitadas (como por exemplo, Data Type e Length) tomando os valores do domínio. Em caso do atributo não pertencer a um domínio, o programador deixará o valor [none] nesta propriedade, e as propriedades correspondentes ao tipo de dados do atributo estarão habilitadas para serem ingressadas.

Data Type: Permite indicar o tipo de dados do atributo, onde é escolhido um dos tipos de dados suportados pelo GeneXus. Dependendo do tipo de dados selecionados, haverá certas propriedades, ou outras, para configurar.

Length: Permite indicar o tamanho do atributo. Se na propriedade Data Type indica que o atributo é numérico, então, dever ser considerado que o tamanho inclui as posições

decimais, o ponto decimal é o sinal. Esta propriedade estará desabilitada quando o tipo de dados escolhido requer estabelecer um tamanho (por exemplo, quando trata do tipo de dados Date).

Decimals: Se a propriedade Data Type indica que o atributo é numérico, esta propriedade éoferecida, para especificar a quantidade de decimais. O valor 0 neste campo, indica que trata

de um inteiro.

Signed: Se na propriedade Data Type se indica que o atributo é numérico, esta propriedade é oferecida, para indicar se tem sinal ou não. O valor por default é “False”, o que indica que não serão representados valores negativos.

ValidationValue Range: Permite indicar uma faixa de valores válidos para o atributo. Por exemplo:• 1:20 30: - significa que os valores válidos são entre 1 e 20; e 30 ou maior.• 1 2 3 4 - significa que os valores válidos são 1, 2, 3 o 4.• 'S' 'N' - significa que os valores válidos são 'S' ou 'N'.

Picture: Permite indicar o formato de edição para a entrada e saída do atributo. Dependendo do tipo de dados do atributo, determinadas propriedades abaixo desta classe são disponibilizadas.O GeneXus fornece um número maior de propriedades dos atributos que as já mencionadas; dependendo do valor que se escolhe para determinada propriedade, são disponibilizadas certas propriedades relacionadas ou outras. É recomendável a leitura de todas as outras propriedades e não somente estas, acessando o Help do GeneXus.________________________________________________________________________________________1 O atributo também pode estar num objeto objeto Web Panel. Nesse caso, de aparecer como coluna, sempre seráoferecido por default para o nome da mesma o de sua propriedade Column Title.2 Os domínios serão abordados mais adiante no curso, mas em resumo, o objetivo dos domínios é realizar definições de dados genéricos. Por exemplo: pode-se definir um domínio de nome Price e tipo de dados Numeric(10,2) e depois associar este domínio para todos os atributos que armazenam preços. Tem a vantagem que se depois desejar modificá-lo por exemplo para Numeric(12,2), tem que modificar somente a definição do domínio e automaticamente todos os atributos baseados nesse domínio herdam essa mudança.

Page 45: 93909254 GENEXUS Heuristica Apostila Teorica

45

Control Info

Um atributo pode associar um tipo de controle. Os possíveis tipos de controles:

- Edit- Radio Button- Check Box- Combo Box- List Box- Dynamic Combo Box- Dynamic List Box

A associação de certo tipo de controle de um atributo, serve para especificar o tipo de controle por default que será usado pelo atributo, cada vez que seja incluso em um form.

Quando um atributo é definido com um tipo de dados básico, o tipo de controle associado a ele é o Edit, podendo ser alterado pelo programador para qualquer um dos outros tipos. Em geral GeneXus escolhe o tipo de controle para um atributo dependendo de seu tipo de dados. Se é um domínio enumerado, como veremos, escolherá Radio Button ou Combo Box, dependendo da quantidade de valores de domínio.

No grupo Control Info do diálogo de edição das propriedades de um atributo, é onde o programador pode mudar o tipo de controle associado ao atributo; e dependendo do tipo de controle escolhido, uma informação distinta pode ser solicitada.

Logo, cada vez que um atributo é agregado em um form, apresentará automaticamente com o tipo de controle que tenha associado.

NotaNo caso de associar ao atributo o tipo Edit, poderá especificar que “disfarce” seus valores, mostrando os de outro atributo (propriedade InputType), e incluso que sugira os valores possíveis ao usuário, a medida que este vá digitando (propriedade Suggest), entre outras, como veremos depois, quando estudarmos “Descrições ao invés de códigos”.

Também se pode escolher a cor da fonte da letra que se deseja associar por default ao atributo, assim como a cor de fundo, de modo que cada vez que se agregue o atributo em um form, se apresente automaticamente com as cores que ele tenha associado (ver grupo Appearance).

Page 46: 93909254 GENEXUS Heuristica Apostila Teorica

46

� Numeric, Character, Date, Boolean

� VarChar- Equivalente a Character, exceto na forma que é armazenada no

BD.- Propriedades Maximum Length e Avarage Length associadas.

� Long Varchar- Permite armazenar textos longos, comentários, etc. (memo).

� DateTime - Permite armazenar uma combinação de data e hora.

� Blob- Permite armazenar qualquer tipo de informação: texto, imagens,

vídeos, planilhas, etc., na base de dados.

TransaçõesAtributos: Tipos de Dados

� Numeric: Permite armazenar dados numéricos. Quando se seleciona este tipo de dados se deve indicar a quantidade total de dígitos do número, a quantidade de posições decimais, e se permite sinal ou não.

Exemplo: Se definimos que o tipo de dados do atributo InvoiceAmount é numérico de tamanho 10, com decimais 2, e sem sinal, estamos especificando que representará números com até 7 dígitos na parte inteira e 2 decimais (7 dígitos na parte inteira + ponto + 2 dígitos para os decimais = 10 dígitos).

� Character: Permite armazenar qualquer tipo de texto (caracteres e dígitos). Para este tipo de dados, deve ser indicado o tamanho.

Exemplo: O atributo CustomerName que utilizamos para armazenar o nome de um cliente, é de tipo Character e sabemos que nunca um nome terá mais de 20 caracteres, podemos fixar o tamanho: 20.

� Date: Permite armazenar uma data. Exemplo: O atributo InvoiceDate que utilizamos para armazenar a data de uma fatura, serádeste tipo de dados.O formato a utilizar para as data (dia-mês-ano, mês-dia-ano), se configura em forma genérica para todo o modelo dentro de um tipo especial de objeto, o objeto Language correspondente a linguagem que vai ser gerado o modelo. O objeto “language” existe para poder ter uma mesma aplicação traduzida em qualquer linguagem.A escolha de apresentar o ano com 2 dígitos ou 4, se configura com a propriedade Picture de cada atributo.

• Boolean: permite que um atributo ou variável assuma os valores lógicos: True, False.

Page 47: 93909254 GENEXUS Heuristica Apostila Teorica

47

• VarChar: Permite armazenar texto de tamanho variável. Sua função, em contraposição ao Character, éotimizar o armazenamento na base de dados. Quando se seleciona o tipo de dados Varchar no diálogo de definição do atributo se acrescentam as 2 seguintes propriedades: Maximum Length e Avarage Length. A primeira é para indicar o tamanho máximo de caracteres que poderão armazenar, enquanto que a segunda é para indicar o tamanho médio de caracteres que se vai armazenar pelo geral. Exemplo: Quando se define um atributo do tipo Character e tamanho 60, se inserimos um dado que ocupa 25 caracteres, a capacidade restante de armazenamento do atributo (35 caracteres), se completa com brancos. O tipo de dados Varchar, aperfeiçoa o armazenamento da seguinte forma: se definir Avarage Length (por exemplo: 25), e Maximum Length (por exemplo: 60); então, se o dado tem tamanho menor ou igual que 25, fica armazenado no campo (se completa brancos), exceto nos casos em que o dado seja de tamanho maior que 25, quando ficam armazenados os primeiros 25 caracteres no campo, e o resto em um área de overflow.Em contrapartida a vantagem de otimização do armazenamento, para os casos que se utilize a área de overflow, será necessário realizar um acesso adicional tanto para a leitura como para a gravação do dado.O tipo de dados Varchar é equivalente ao tipo Character em todos os sentidos, exceto na forma em que armazena os caracteres na base de dados. Podem ser aplicadas todas as funções e operadores existentes para o tipo de dados Character. Se o DBMS não suporta este tipo de dados, se criará o atributo do tipo Character.

�Long Varchar: Permite definir um atributo memo; isto é, normalmente utilizado para armazenar textos grandes, comentários, etc. Ao selecionar este tipo de dados deve-se indicar um tamanho máximo de caracteres. Existem duas funções para manipular este tipo de dados: GXMLines e GXGetMLi. GXMLines retorna a quantidade de linhas que tem um atributo Long Varchar, tendo como parâmetro o nome do atributo, e a quantidade de caracteres que se deseja considerar por linha.Exemplo: &cantlin = GXMLines( AtribMemo, 40 ). O GXGetMLi por sua vez, extrai uma linha do atributo Long Varchar (para depois imprimi-la, por exemplo), tendo como parâmetro o nome do atributo, o número da linha desejado, e a quantidade de caracteres que deseja considerar por linha.Exemplo: &txt = GXGetMLi( AtribMemo, 1, 40 ).Geralmente estas 2 funções são usadas combinadas, já que primeiro consulta a quantidade de linhas que tem certo atributo Long Varchar, indicando a quantidade desejada de caracteres por linha, e depois prossegue extraindo o conteúdo das linhas, utilizando um loop até chegar à última linha, e desta forma eles são impressos, por exemplo.

•DateTime: Permite armazenar uma combinação de data e hora.

A propriedade Picture deste tipo de dados, permite escolher o que desejamos mostrar sobre a data, e o que desejamos mostrar sobre a hora.Referente a data podemos escolher entre: não mudá-la, mudá-la e apresentar o ano com 2 dígitos, mudá-la e apresentar o ano com 4 dígitos. Referente a hora podemos escolher entre: mudar somente 2 dígitos para a hora (não administrando minutos nem segundos), mudar 2 dígitos para a hora e 2 dígitos para os minutos (não administrando segundos), mudar 2 dígitos para a hora, 2 dígitos para os minutos e 2 dígitos para os segundos.Os valores antes mencionados não afetam a forma de armazenar o tipo de dados, caso não seja especificado a forma de aceitar ou mostrar seu conteúdo.Nota: Em caso de não alterar a data, só a hora, o valor da data que ficará no campo será o mínimo suportado pelo DBMS, e será reconhecido pelo GeneXus como data vazia ou nula. No que se dizrespeito à hora, os valores não aceitados (minutos e/ou segundos) serão armazenados com valor zero.

� Blob: As aplicações requerem cada vez mais manter e trabalhar com este tipo de informação.O tipo de dados Blob permite armazenar esta diversidade de informação na própria base de dados, aproveitando assim os diferentes mecanismos de integridade e controle fornecido pelos DBMSs.Este tipo de dados somente pode ser utilizado quando se tem um DBMS.

Para aprofundar o conhecimento nesse tipo de dados entrar no Help GeneXus.

Page 48: 93909254 GENEXUS Heuristica Apostila Teorica

48

� Em todo objeto GeneXus é possível definir variáveis.

� As variáveis são visíveis somente dentro do objeto; isto é, são locais.

� Editor similar ao da estrutura das transações:

TransaçõesDefinição de variáveis

� É possível definir variáveis do tipo coleção (qualquer tipo de dados).

Para definir variáveis em determinado objeto, deve selecionar o seletor Variáveis, como se mostra na figura.Este seletor mostra variáveis definidas por default (Standard variáveis, como por exemplo a variável Today que contem a data do sistema) para o objeto, e permite definir variáveis novas através de um editor similar ao das transações.

Também se pode ir a opção Insert do menubar e escolher Variables. No quadro de diálogo que se mostra para selecionar New Variável.

Este diálogo solicita o nome da variável, sua descrição, tipo de dados e tamanho, o domínio, de forma análoga quando se define um atributo.A propriedade Dimensions permite indicar se a variável será escalar ou se tratará de um vetor (1 dimensão) o matriz (2 dimensões). O valor que oferece por default esta propriedade é escalar.

Page 49: 93909254 GENEXUS Heuristica Apostila Teorica

49

“Based On”Oferece uma forma rápida de definir uma variável. Quando se seleciona, se mostra um diálogo que mostra todos os atributos definidos na base de conhecimento; em dito diálogo, simplesmente se deve selecionar um atributo, e em seguida se defini automaticamente uma variável com o mesmo nome e a mesma definição que o atributo. Vale declarar que se podem selecionar vários atributos, criando nesse caso uma variável para cada atributo selecionado, com suas mesmas características.

Por outra lado, é possível definir variáveis dentro do editor de código de cada objeto (source, eventos, etc.), fazendo uso do menu contextual (botão direito) depois de escrever o nome da variável. Isto é, ao escrever &nomeDeVariavel (ex: &x) e pressionar botão direito do mouse. No menu contextual depois escolher Add Variável.

Variáveis coleçãoÉ possível definir variáveis coleção sobre qualquer tipo de dados oferecido por GeneXus.Para isso basta clicar na correspondente casinha no editor de variáveis, ou indicar o valor True na propriedade Collection associada as variáveis.Para percorrer depois os itens colecionados em dita variável, se deve utilizar a estrutura de controle “For in”.

Por exemplo, temos definido a variável &myNumbers de tipo Numeric(4.0)Para percorrer os valores armazenados se deverá criar uma nova variável de tipo Numeric (4.0). Criamos então a variável &OneNumber, e declaramos:

For &OneNumber in &myNumbers----------

Endfor

Page 50: 93909254 GENEXUS Heuristica Apostila Teorica

50

• Objetivo: Realizar definições genéricas.

• Quando os domínios devem ser utilizados?• Atributos e/ou variáveis com a mesma definição.

Exemplo:

TransaçõesDomínios

Atributos

Domínios

InvoiceDetailAmount Valor total da linhaProductPrice Preço do produto

É comum ter numa base de conhecimento, atributos que compartilhem definições similares, mas que não tenham nenhuma relação. Por exemplo, é comum definir todos os nomes, como atributos do tipo character e tamanho 20; ou todos os valores, como atributos do tipo numérico e tamanho 10.2.

O objetivo dos domínios é permitir realizar definições genéricas. Como exemplo, o atributo InvoiceDetailAmount é do tipo numérico e tamanho 10.2, assim como o atributo ProductPrice que é do mesmo tipo e tamanho, na mesma base de conhecimento. Desse modo, podemos definir um domínio de nome Price, que seja do tipo numérico com tamanho 10.2, e a cada um dos atributos mencionados atribuir o domínio valores Price. A vantagem de fazê-lo assim, é que se no futuro surgir a necessidade de mudar a definição dos atributos que representam valores, a mudança é realizada uma única vez (no domínio Price), propagando-se este automaticamente aos atributos InvoiceDetailAmount e ProductPrice.

Page 51: 93909254 GENEXUS Heuristica Apostila Teorica

51

• Domínios enumerados: manter o estado do cliente: Active, On Hold, Closed � dominio Status

TransaçõesDomínios

Atributo CustomerStatus de domínio Status

Se trabalha com os nomes ao invés de trabalhar com os valores:

CustomerStatus = Status.Active

Existe a possibilidade de trabalhar com domínios enumerados (aqueles que representam valores finitos e particulares). Nas linguagens de programação são bem conhecidos. O caso típico de uso é para os dias da semana, quando se precisa que uma variável tenha um dos seguintes valores: Segunda-feira, Terça-feira, Quarta-feira, Quinta-feira, Sexta-feira, Sábado, Domingo.

Em nosso caso, vamos adicionar à estrutura da transação Customer um atributo que representa o estado do cliente no sistema num determinado momento. Pode estar active, on hold ou closed.

Uma forma de representá-lo é definindo um domínio Status, que corresponde ao tipo de dados Character(1) mas para o qual explicitamente dizemos que não queremos que possa ter todos os valores desse tipo de dados, mas apenas 3: A, H e C, e dizemos também que queremos trabalhar dando nomes a estes 3 valores e trabalhar com seus nomes. Assim, ao A associamos o nome ‘Active’, ao H ‘OnHold’ e ao C ‘Closed’. Associando ao atributo CustomerStatus o domínio Status (observar que, devido à terminação do nome do atributo, ao inserir o atributo na estrutura depois de ter definido o domínio isto é automaticamente sugerido pelo GeneXus) no atributo da tabela internamente será salvo um dos 3 valores: A, H ou C, porém, não teremos de lembrar esses valores, mas sim seus códigos: Active, OnHold e Closed.

Já tínhamos outro atributo com domínio enumerado: CustomerGender. Nesse caso, possuía apenas 2 valores: Female e Male.

Observar como o Control Info oferece para o ControlType um Combo Box ao invés de um Edit. Isto fará sentido quando vermos o Form de uma transação um pouco mais adiante.

Page 52: 93909254 GENEXUS Heuristica Apostila Teorica

52

TransaçõesDomínios

Assim como o domínio pode ser associado a um atributo (e a outro domínio), da mesma forma pode ser associado a uma variável. Um mesmo domínio pode ser referido tanto a atributos como a variáveis, já que o objetivo é exatamente o mesmo.

Como definir um domínio?Existem vários caminhos:1) Opção Domains do Folder View: Mediante um editor similar ao das variáveis, pode ser definido um novo domínio. 2) Visto que na tela de configuração das propriedades de um atributo é onde se atribui a um atributo um domínio existente, em dita tela, se oferece um botão para criar um domínio novo. Idem com o diálogo de definição de variáveis.3) Na estrutura da transação é possível definir um novo domínio no campo de definição do tipo de dados de um atributo, simplesmente escrevendo sobre essa mesma linha, o nome do domínio, e atribuindo o tipo de dados. Por exemplo, digitando Price = Numeric(10.2) sobre a coluna Type do atributo que se está definindo, fica também definido o domínio de nome Price, com o tipo de dados Numeric(10.2).

Page 53: 93909254 GENEXUS Heuristica Apostila Teorica

53

� Cada transação tem um Web Form.

� Por default é criado ao gravar a estrutura da transação, podendo ser modificado pelo programador.

TransaçõesWeb Form

Para cada transação, GeneXus cria um form web, que será a interface com o usuário.

É criado por default por GeneXus ao momento de gravar a estrutura da transação, e contem todos os atributos incluídos na mesma, com suas respectivas descrições, além de alguns botões.

Se bem é criado por default, é possível modificá-lo para deixá-lo mais vistoso, mudar por exemplo controles de tipo edit a outros tipos de controles, agregar e/ou tirar botões, etc.

Page 54: 93909254 GENEXUS Heuristica Apostila Teorica

54

TransaçõesWeb Form da transação “Invoice”

GRID

Control “Error Viewer”

No exemplo que se mostra o form Web correspondente a transação “Invoice”. Através deste form o usuário final poderá ingressar, modificar e eliminar faturas na aplicação Web.

O controle Error Viewer se utiliza para poder colocar e programar no lugar onde queremos que as mensagens gerais sejam mostradas ao usuário final de uma transação Web.Poderemos especificar entre outras coisas o lugar onde queremos que este controle esteja dentro do form, seu tipo de letra, cor, etc..Observe que o segundo nível da transação aparece no form como um control grid.

Page 55: 93909254 GENEXUS Heuristica Apostila Teorica

55

TransaçõesWeb Form da transação “Customer”

Domínios enumerados �controles Combo Box

Domínios básicos �controles Edit

Page 56: 93909254 GENEXUS Heuristica Apostila Teorica

56

TransaçõesPaletas de ferramentas para o desenho de Forms

Inserir controles:

Cortar, copiar e colocar controles:

• Opção View do Menubar \ Other Tool Windows \Toolbox

Podemos definir um controle como uma área da interface com o usuário, que tem uma forma e um comportamento determinado.Existem diferentes controles:

- Texto: Permite colocar texto fixo- Atributo/Variável: Permite colocar atributos ou variáveis.- Linha horizontal- Error Viewer- Tabela: Inserir tabelas no form- Grid: Permite definir grids de dados.- Botão: Permite incluir botões nos forms. - Bitmap: Permite definir bitmaps estáticos, etc.

Paleta de ferramentas para inserir controles: Quando se está editando um form, se encontra disponível uma paleta de ferramentas (Toolbox) que oferece os controles possíveis de inserir no mesmo. Simplesmente se deve selecionar o controle e arrastá-lo sobre o form.

Page 57: 93909254 GENEXUS Heuristica Apostila Teorica

57

• Cada controle do Web form pode ter associada uma classe, de um objeto theme (tema) determinado que está associado ao objeto.

• Ao criar uma KB, se cria por default o tema “GeneXus X” e todos os objetos criados terão este tema associado.

• Isto permite que o desenho da interface seja independente da programação.• Cada tema vai ter muitas classes definidas para cada

tipo de controle.• O analista somente associa um tema ao objeto, e uma

classe a cada controle do form e não precisa se preocupar com o desenho dos mesmos.

• O controle herda o desenho da classe do tema associado.

TransaçõesControles em Web Form

Para separar os aspectos de desenho gráfico de um site web, dos aspectos de programação propriamente dito, existe um tipo de objeto chamado Theme (Tema em português).

O objetivo desta separação é paralelizar o desenvolvimento de um site Web, permitindo ao programador aproximar-se das tarefas de programação, e apoiar-se em um design gráfico para que defina as questões de desenho. Desta maneira o design gráfico configurará o “tema”escolhido pelo programador, e o programador somente deverá aplicá-lo aos objetos de sua base de conhecimento.Um objeto “tema” conterá um conjunto de classes, para cada tipo de controle dos que podem aparecer no form Web de um objeto GeneXus. Por exemplo, terá várias classes para o controle botão, algumas para o controle atributo, uma classe para o controle Error Viewer, etc.

Quando se cria uma base de conhecimento, automaticamente aparecerá dentro do Folder View da pasta “Customazation” com objetos Theme pré-definidos que poderão ser importados na KB. Por default se importa o de nome “Genexus X”. Este tema contem um conjunto de classesassociadas aos diferentes controles existentes.

Os objetos com form Web que vão sendo criados terão por default associado este Theme, e cada controle que apareça em seus forms terá associado uma classe desse tema, para este controle.

Page 58: 93909254 GENEXUS Heuristica Apostila Teorica

58

TransaçõesControles em Web Form

Deste modo, quando o analista cria a transação "Customer“ e informa sua estrutura, ao gravá-la pode ver que o Form Web terá automaticamente o aspecto mostrado na tela acima à esquerda. Quem deu o formato a todos os controles se não foi o analista exatamente?

Pois bem, todas as transações terão associado por default o tema “GeneXus X” e todos os controle colocados no form, terão classes deste tema associadas.

Se sobre o Text Bloxk (controle de texto) mostrado acima (Name), se editam suas propriedades (F4), pode-se observar a propriedade Class, que tem configurada a classe TextBlock. Esta propriedade pode ser mudada pelo analista. Ao clicar o combo box poderemos ver uma lista de classes possíveis para esse controle (são as que figuram no tema associado). A direita mudamos a classe para uma de nome Title e no form podemos ver a repercussão no desenho do TextBlock.

Não entraremos em detalhe neste tema no presente curso.

Page 59: 93909254 GENEXUS Heuristica Apostila Teorica

59

Demo

�Como executar a aplicação?

Opção Build \ Run Developer Menu, ou pressionar a tecla F5.

F5: Dispara automaticamente todas as ações necessárias para executar a aplicação

Se BD não existe, se cria automaticamente (sempre e quando usuário e password tenham permissão de DBCreator)

Lembremos que no momento de criação da KB, se indicou o gerador por default a ser utilizado. Agora deve completar a informação necessária para terminar de definir o ambiente de implementação.

Database name: Nome da base de dados que estará associada a aplicação.

Server name: Nome do servidor da base de dados que a administra.

Use trusted connection: Yes (deverá indicar o usuário e contra-senha válido no DBMS)No

Considerações:Se a base de dados não existir, GeneXus a criará, sempre e quando o usuário e contra-senha configurados na janela de diálogo tenham permissão de DBCreator no DBMS.

Page 60: 93909254 GENEXUS Heuristica Apostila Teorica

60

Processo de Build

O processo de Build inclui todas as tarefas necessárias para a execução da aplicação: Verificação de alterações na BD, Reorganização (se for necessário), Especificação, Geração e Compilação. Não inclui a execução.

KB

SPECIFICATION

GENERATION

COMPILATION

REORGANIZATION

DBASE IMPACT ANALYSIS

APPLICATION

Aplicação pronta para executar

O processo de Build é executado em background, permitindo realizar outras tarefas enquanto o mesmo estiver correndo, por exemplo continuar com o desenvolvimento.

Cada vez que se executa a aplicação (F5), GeneXus realiza uma comparação entre as definições atuais de todos os objetos e as definições da última execução. Esta comparação que o GeneXus faz, se chama análise de impacto. Este nome é auto-descritivo: GeneXus analisa o impacto causado pelas novas definições, e o resultado da análise de impacto é um relatório de análise de impacto(IAR: Impact Analisis Report) que informa ao programador quais alterações físicas ou estruturais precisam ser realizadas na base de dados associada.

Se por exemplo se criou uma nova transação, isto provocará (tal como é o objetivo das transações) que se criam as tabelas correspondentes na base de dados (ver página seguinte).

Page 61: 93909254 GENEXUS Heuristica Apostila Teorica

61

IAR e Reorganização

‘Create’ se estiver tudo OK �serão construídos os programas no Environment e vai executar...

No exemplo, criar as 2 transações “Customer” e “Invoice” e dar F5, aparece o relatório de análise de impacto que pode se ver, onde são listados entre outras coisas, a estrutura que terá cada tabela que será criada, com seus atributos, tipo de dados, os índices que serão criados sobre as tabelas, as chaves estrangeiras (observar que o relatório da tabela INVOICE diz que se referenciará a tabela CUSTOMER (isto acontece pelo atributo CustomerId da transação Invoice que se chama igual que o atributo CustomerId de CUSTOMER, constituindo portanto uma chave estrangeira a dita tabela).

Se o programador está de acordo com os alterações estruturais informadas no relatório de análise de impacto, poderá prosseguir, passando a reorganizar a base de dados. O término reorganizar refere a efetuar alterações físicas na base de dados.

Se na alteração o programador encontra algo informado no relatório de análise de impacto não era o que pretendia obter, poderá não efetuar a reorganização, e as redefinições convenientes são criadas.

Quando se decide efetuar uma reorganização GeneXus gera programas (na linguagem escolhida quando se criou a KB) que implementam as modificações a serem realizadas na base de dados. A execução destes programas tem como resultado a obtenção de uma nova versão da base de dados com as alterações efetuadas.

O seguinte passo será obter os programas da aplicação associados aos objetos GeneXus. Para isso GeneXus deverá especificar, gerar e compilar os programas da aplicação.

Especificar um objeto significa que GeneXus analisará tudo o que foi definido em cada um dos elementos que o compõem: estrutura, forms, ou outros elementos segundo corresponda. GeneXus verificará a sintaxe das definições, a validez do definido, e como resultado da especificação mostraráao usuário uma listagem de navegação, na qual informará a lógica interpretado, e se tem alguma advertência ou erro.Gerar um objeto, significa que GeneXus escreverá linhas de código que implementem a programação do mesmo, na linguagem escolhida.Compilar os programas significa que o código escrito (gerado) seja convertido a linguagem de máquina (binário) para que possam ser executados.

Page 62: 93909254 GENEXUS Heuristica Apostila Teorica

62

Execução

Page 63: 93909254 GENEXUS Heuristica Apostila Teorica

63

Opção “Build” da barra domenu de GeneXus

Opções do item “Build”:

• Build All e Rebuild All: Estas opções são utilizadas quando não se está seguro do impacto das alterações e se quer ter atualizadas as últimas definições. A opção Build All realiza todas as ações que estejam pendentes, enquanto que Rebuild All força todas elas.As ações são:

- Salvar todos os objetos que não estejam salvos.- Reorganizar a base de dados, se for necessário.- Especificar somente os objetos que foram modificados (se selecionou Build All), ou

forçar a especificação de todos (selecionou Rebuild All).- Gerar os objetos- Compilar os objetos definidos Main- Compilar o Developer Menu

• Build / Rebuild Developer Menu: Similar as opções anteriores mas aplicadas somente ao Developer Menu. Não o executa.

• Run Developer Menu: Executa todas as ações que estejam pendentes e executa o Developer Menu.

- Salva todos os objetos que não estejam salvos.- Reorganizá-la a base de dados, se for necessário.- Especifica somente os objetos que foram modificados.- Gera os objetos.- Compila e executa o Developer Menu.

Page 64: 93909254 GENEXUS Heuristica Apostila Teorica

64

• Build / Rebuild / Run options: Opções aplicadas a objetos definidos como Main. Disparam as seguintes ações:

- Salvam os objetos que não estejam salvos.- Reorganização a base de dados, se for necessário.- São especificados somente os objetos que sofrerem alterações (se selecionou

Build), ou se força a especificação de todos os objetos pertencentes a árvore de chamadas do objeto Main (quando selecionado Rebuild).

- Geração- Compilação do objeto Main- Execução do objeto Main (quando selecionado a opção Run)

• Build / Run with this only options: Build e execução do objeto definido como Startup. Por default o objeto Startup é o Developer Menu.

- Salvam todos objetos que não estejam salvos.- Reorganização a base de dados, se for necessário.- Especificam somente o objeto selecionado.- Geram somente o objeto selecionado.- Compilam o objeto Startup- Se executa o objeto Startup (se selecionou Run).

• Set As Startup Object: O objeto indicado passará a ser o objeto Startup da aplicação, ou seja o objeto que finalmente se executa quando se pressione a tecla F5. Por default o objeto Startup é o Developer Menu.

• Create Database Tables: Cria novamente as tabelas. Se perdem os dados que poderão estar armazenados previamente.

• Impact Database Tables: Se realiza um impacto sobre as tabelas da base de dados.

Page 65: 93909254 GENEXUS Heuristica Apostila Teorica

65

• Os diferentes modos podem ocorrer ao executar uma transação, dependendo da operação que se realize:

Modo Insert: Indica que se está efetuando uma inserção

Modo Update: Indica que se está efetuando uma atualização

Modo Delete: Indica que se está efetuando uma eliminação

Modo Display: Indica que se está efetuando uma consulta

TransaçõesModos em tempo de execução

Dependendo do ambiente de geração, existem algumas diferenças referentes àoperacionalidade das transações em tempo de execução. Diante da plataforma, cada vez que se realize uma operação de inserção, atualização, eliminação, ou consulta da base de dados através de uma transação, existem um modo associado.

Page 66: 93909254 GENEXUS Heuristica Apostila Teorica

66

TransaçõesEm tempo de execução

&GxRemove:Variável do sistema para eliminar linhas.

Para agregar uma nova linha

Sempre vai mostrar um número de linhas vazias fixas para ser ingressadas pelo usuário (valor configurável pelo analista a nível do grid, em sua propriedade “Rows”). Por default são mostradas 5 linhas vazias.Se o usuário ingressou as 5 linhas e necessita ingressar mais, bastará pressionar New Row, ou simplesmente pressionar Enter e uma nova linha é agregada.

Para poder eliminar linhas em execução, GeneXus incorpora automaticamente no grid do form Web uma primeira coluna com uma variável do sistema de nome &GxRemove, em forma de check box. Para visualizar este check box, se deve pressionar o botão direito do mouse sobre a linha a ser eliminada. Depois deve pressionar o botão Confirm.

Page 67: 93909254 GENEXUS Heuristica Apostila Teorica

67

TransaçõesMaster Pages

As Master Pages fornecem uma forma de centralizar o layout e o comportamento comum em somente um objeto e reutilizá-lo em qualquer outro objeto sem ter que programar.

Criadas automaticamente com a KBCriadas automaticamente com a KB

Ter um look&feel consistente é hoje em dia um dever de toda aplicação Web.Criar e manter cada página de uma aplicação Web assegurando a consistência com o resto do site toma grande tempo de programação.

Ao criar uma base de conhecimento GeneXus X cria também dois objetos de tipo Master Page:AppMasterPage: Para a aplicação.PromptMasterPage: Para os prompts.

As Master Pages fornecem uma forma de centralizar o layout e o comportamento comum em um objeto somente e reutilizá-lo em qualquer outro objeto sem ter que programar. Isto significa que a modificação de alguma parte do layout ou do comportamento comum é tão fácil como modificar em um único objeto e pronto!

Em uma mesma base de conhecimento podem ser definidas quantas Master Pages como se deseje.

Quando estudarmos o objeto Web Panel compreenderemos que uma Master Page será em particular uma Web Panel categorizado como “Master Page” com todo o Layout e comportamento comum a todas as páginas do site, dentro deste objeto se deixa um espaço para carregar em cada oportunidade a página que corresponda (o conteído variável do site). Isso se faz no controle presente no form de nome Content Placeholder.

Page 68: 93909254 GENEXUS Heuristica Apostila Teorica

68

TransaçõesMaster Pages

• Propriedade Master Page

As páginas web que implementam o conteúdo variável, se associam a Master Page, de maneira que cada vez que sejam executadas, carreguem com esse “contexto” (o da Master Page).

Page 69: 93909254 GENEXUS Heuristica Apostila Teorica

69

Demo

• Agregar a transação “Product” que não foi definida e ver como ficam os ícones em “Invoice”

O que acontece ao fazer F5?

Observe como depois de criar a transação “Product” GeneXus normaliza e indica graficamente na estrutura da transação “Invoice” que os atributos, antes próprios da tabela INVOICEDETAIL, agora serão inferidos, através da nova chave estrangeira ProductId.

A chave primária da tabela INVOICEDETAIL continua sendo composta: {InvoiceId, ProductId}, mas além disso, o atributo ProductId sozinho, será uma FK na tabela PRODUCT, a partir da qual se inferem os atributos ProductDescription e ProductPrice.

Depois do F5, naturalmente será informado a necessidade de reorganizar a base de dados, criandoa tabela PRODUCT e modificando a tabela INVOICEDETAIL da maneira que indicamos nos parágrafos anteriores.

O que acontece com os registros já existentes na tabela INVOICEDETAIL, para os que possuiam valores de ProductDescription e ProductPrice?Como será visto quando executar, o programa de reorganização agrega uma rotina para criar os registros de produtos na tabela PRODUCT com essa informação pré-existente. O que acontecerá se existia o mesmo produto em várias linhas de diferentes faturas?

Page 70: 93909254 GENEXUS Heuristica Apostila Teorica

70

INTEGRIDADEREFERENCIAL

Page 71: 93909254 GENEXUS Heuristica Apostila Teorica

71

CUSTOMER

COUNTRY

CustomerId*CustomerName

………CountryId

CountryId*CountryName

1

N

Integridade ReferencialDiagramas

O conceito de integridade referencial é um conceito que se refere às bases de dados relacionais.Se refere que deve fazer a consistência entre os dados das diferentes tabelas de uma base de dados relacional.

As tabelas de uma base de dados relacional estão relacionadas por atributos que tem em comum. Estas relações implicam que os dados das tabelas não sejam independentes, ou seja, ao inserir, modificar ou eliminar registros de uma tabela tem que ser levado em consideração os dados das outras tabelas para que sempre se conserve a consistência da informação na base de dados.

Se temos um modelo de dados relacional com as tabelas:

COUNTRY (CountryId, CountryName)Chave Primária: CountryId

CUSTOMER (CustomerId, CustomerName, CustomerAddress, CustomerGender, CountryId)

Chave Primária: CustomerId

Chave Estrangeira: CountryId (COUNTRY)

O fato do atributo CountryId está na tabela CUSTOMER ser uma chave estrangeira com respeito a tabela COUNTRY, estabelece uma relação entre ambas as tabelas. A relação entre elas pode ser representada com o diagrama mostrado.

No Diagrama de Bachman, a seta simplesmente representa a existência de uma instancia da tabela mostrada, para cada instancia da outra (para cada cliente existe um e somente um país). A seta dupla representa a ocorrência de várias instâncias da tabela apontada, para cada instancia de outra tabela (para cada país, existem muitos clientes).Dizemos que a relação entre a tabela COUNTRY e a tabela CUSTOMER é 1 de N (1 a muitos). Reciprocamente, a relação entre CUSTOMER e COUNTRY é N de 1 (muitos a 1).

Page 72: 93909254 GENEXUS Heuristica Apostila Teorica

72

CUSTOMER

COUNTRY

1

N

Na transação “Customer”:• se inserir um novo registro, ou• se modificar o CountryId de um registro

Tem que verificar existência do COUNTRY referenciado.

Na transação “Country”:• se quer eliminar um registro

Tem que verificar se não existe nenhum CUSTOMER que o referencie.

CUSTOMER

COUNTRY

1

N

Integridade ReferencialDiagramas

Na terminologia GeneXus, dizemos que existe uma relação de subordinação entre ambas as tabelas. Dizemos que:

COUNTRY está superordinada a CUSTOMERCUSTOMER está subordinada a COUNTRY

Significando que:

Quando se cria ou modifica um registro na tabela subordinada (CUSTOMER), deve existir o registro relacionado na tabela superordinada (COUNTRY).

• Quando se elimina um registro na tabela superordinada (COUNTRY), não devem existirregistros relacionados na tabela subordinada (CUSTOMER).

Devido a esta relação entre as tabelas, a informação contida nelas não é independente, e énecessário realizar controles para que os dados sejam consistentes. A estes controles se chama de Integridade Referencial e basicamente são os seguintes:

• Quando se insere ou modifica um registro na tabela CUSTOMER, o valor ingressado no atributo que é chave estrangeira (CountryId), deve existir como valor de chave primária de um registro na tabela COUNTRY.

• Quando se elimina um registro na tabela COUNTRY, não devem existir registros na tabela CUSTOMER cujos valores da chave estrangeira (CountryId), sejam iguais ao valor da chave primária do registro que se deseja eliminar.

•GeneXus gera os programas associados as transações, incluindo no código gerado estes controles de Integridade Referencial. Por esta razão, se o usuário final insere (ou modifica) um cliente através da transação "Customer", é validado automaticamente que o valor ingressado no código de país CountryId, exista como chave primária de um registro na tabela COUNTRY. Em caso de falhar este controle de integridade referencial, uma mensagem émostrada ao usuário indicando que não se encontrou esse país.

Page 73: 93909254 GENEXUS Heuristica Apostila Teorica

73

Integridade ReferencialÍndices

Os índices são vias de acesso eficientes as tabelas. GeneXus cria automaticamente alguns deles, e outros deverão ser criados pelo programador quando este assim o determine, baseando-se em critérios de otimização.Existem quatro tipos de índices em GeneXus:

• Primários• Estrangeiros• De usuário•Temporários

De todos eles, os únicos que não são criados automaticamente por GeneXus são os “de usuário”.Enquanto aos tipos de índices que são criados por GeneXus, a diferença que existe entre eles é o momento em que são criados e o tempo durante o qual se mantêm.

- Os índices primários e estrangeiros são criados no momento de criar ou reorganizar as tabelas que compõem a base de dados, e depois são mantidos automaticamente por GeneXus.

- Os índices temporários, por sua vez, são criados ao executar as aplicações, para acessar a tabelas ordenadas por algum atributo ou conjunto de atributos para ele/eles que não existe um índice de usuário criado; estes se criam em tempo de execução das aplicações, são utilizados e depois são eliminados.

ÍNDICES PRIMÁRIOS E ESTRANGEIROS

GeneXus cria para cada tabela um índice por sua chave primária (índice primário), e um índice por cada chave estrangeira que a tabela tenha (índices estrangeiros). Por que criar índices primários e estrangeiros para as tabelas no início de forma automática, sendo que depois devem ser mantidos? Sejam as tabelas COUNTRY e CUSTOMER, que vimos um par de páginas atrás, criadas em nosso modelo de dados a partir das estruturas das transações "Country" e "Customer”. Existe entre estas tabelas uma relação 1-N, que ocorre pelo fato de que o atributo CountryId na tabela CUSTOMER éuma chave estrangeira com respeito a tabela COUNTRY.

Page 74: 93909254 GENEXUS Heuristica Apostila Teorica

74

CustomerId*CustomerName

...CountryId

CountryId*CountryName

ICountryPK PK

FK

ICustomer

ICustomer1

1 Uruguay2 United States3 China

CountryId CountryName CustomerId CustomerName CountryId

4 Ann Silver 11 John Smith 13 Mary Jones 12 Jessica Deep 2

Se na transação “Country”queremos eliminar “United States”:

O programa deve buscar sobre CUSTOMER se existe registro com CountryId = 2 � para que essa busca seja eficiente: índice estrangeiro (ICustomer1)

Integridade ReferencialÍndices primários e estrangeiros

Por existir esta relação, o GeneXus inclui nos programas associados às transações "Country" e "Customer", os controles de integridade referencial pertinentes. Estes controles são:• Se o usuário final insere ou modifica um cliente através da transação "Customer", serávalidado automaticamente assim que o valor ingressado na chave estrangeira CountryId exista como chave primária de um registro na tabela COUNTRY. Caso o controle de integridade referencial falhe é indicado ao usuário que não foi encontrado este país. Para controlar isto, deve-se buscar na tabela COUNTRY a existência de um registro que tenha esse valor de CountryId como chave primária; devemos consultar a tabela COUNTRY, buscando pela chave primária, sendo que, a busca pode ser otimizada se existir um índice pela chave primária em dita tabela.• Se o usuário final tentar eliminar um país através da transação "Country" é validado automaticamente que não existam clientes no país atribuído com chave estrangeira; em caso de encontrar um registro na tabela CUSTOMER, cujo valor de chave estrangeira CountryId seja o que se deseja eliminar, será indicado ao usuário que não é possível eliminar o país (já que do contrário ficariam dados inconsistentes na base de dados). Para controlar isto, devemos consultar a tabela CUSTOMER, buscando pela chave estrangeira CountryId. Esta busca será otimizada se existir um índice por CountryId na mesma.

Controle de unicidade de chave primáriaOutro controle que o GeneXus também inclui nos programas associados às transações é a unicidade da Chave Primária; isto é, em nenhuma tabela poderão existir dois registros com o mesmo valor na Chave Primária. Para controlar isto, quando o usuário final tentar inserir um registro, é validado automaticamente que o valor ingressado para a Chave Primária, não exista como Chave Primária de outro registro na tabela. Para fazer esta busca com eficiência, devemos utilizar o índice primário da tabela.Concluindo, o GeneXus ao criar cada tabela da base de dados, cria também seu índice primário, e um índice estrangeiro por cada Chave Estrangeira que a tabela contenha.A criação destes índices permite realizar os controles de integridade referencial e de unicidade de chave primária acessando as tabelas de forma eficiente.

Page 75: 93909254 GENEXUS Heuristica Apostila Teorica

75

• O analista os cria sobre uma tabela. Deve ser categorizado conforme for aceito valores repetidos (duplicate) ou não (unique).

• Se na realidade modelada, dois clientes podem ter o mesmo nome:

CustomerId CustomerName CountryId

1 Ann 12 Ann 23 Mary 1

Integridade ReferencialÍndices de Usuário

ÍNDICES DE USUÁRIO

Estes índices devem ser definidos explicitamente pelo analista. Não são definidos automaticamente. Dividem-se em duplicate e unique:

Um índice de usuário duplicate é definido para atributos de uma tabela que possam ter vários registros com o mesmo valor nos mesmo (isto é, se define para atributos que não são uma chave candidata).

Este tipo de índices se define fundamentalmente para acessar os dados ordenados por determinados atributos de forma eficiente. Por exemplo, supondo que o nome do cliente não é chave na tabela de CUSTOMER (seus valores podem se repetir) poderemos definir um índice de usuário duplicate para o atributo CustomerName, sendo muito útil para realizar consultas e relatórios que necessitem que sejam ordenados por nome.

Um índice de usuário unique é utilizado para especificar que um conjunto de atributos échave candidata em uma tabela (diferente da chave primária).Esta é a forma de representar chaves candidatas no modelo de dados. Com isso conseguimos que o GeneXus incorpore automaticamente o controle de unicidade correspondente nas transações associadas. Por exemplo, se o nome do cliente não pode ser repetido, a forma de representá-lo e fazer com que o GeneXus o controle automaticamente é definindo na tabela CUSTOMER um índice de usuário unique pelo atributo CustomerName.

Page 76: 93909254 GENEXUS Heuristica Apostila Teorica

76

• Se o nome não pode ser repetido (é portanto um atributo chave da tabela)

• A forma de definir chaves candidatas no modelo de dados é através de índices unique. GeneXus passará a incorporar controles nas transações, utilizando o índice, para não permitir a inserção de registros duplicados.

CustomerId CustomerName CountryId

1 John Smith 12 Ann Jones 23 Richard Land 1

Ao tentar ingressar um novo cliente com nome “Ann Jones” a transação dará um erro de registro duplicado.

Integridade ReferencialÍndices de Usuário

Índices unique (chaves candidatas)

Em uma tabela da base de dados podem existir vários conjuntos de atributos cujos valores sejam únicos na realidade. Dizemos que cada um desses conjuntos é uma chave da tabela. Depois, o analista escolhe uma das chaves como a chave primária. GeneXus identifica a chave primária da tabela de acordo com os atributos que foram qualificados pelo analista com o símbolo da chave.

Vamos supor que na realidade além de poder identificar um cliente por seu código ou possa ser identificado por sua carteira de identidade. Neste caso tanto o atributo CustomerId como o atributo CustomerSSN (armazena o Nro da Carteira de Identidade) seriam chaves da tabela CUSTOMER. Ao indicar que CustomerId é o identificador da transação, o GeneXus cria automaticamente um índice primário para dito atributo e controla a unicidade dos valores ingressados para o mesmo.

O que acontecerá com a carteira de identidade do cliente? Ao ser este atributo chave, queremos que o GeneXus garanta da mesma forma, não permitindo que seja inserido um registro, já existindo outro com o mesmo valor da carteira de identidade (CustomerSSN). Para poder fazer este controle de forma eficiente, o GeneXus deveria ter um índice para cada atributo chave.

A forma de definir em GeneXus que um atributo ou um conjunto de atributos é Chave alternativa ou candidata e que para tanto deve-se checar sua unicidade, é definindo um índice de usuário composto por esse atributo ou conjunto de atributos, e o qualificando como “unique” ao invés de “duplicate”, que é o valor por default de um índice de usuário.

A partir daí, GeneXus inclui na lógica da transação esse controle de unicidade utilizando esse índice definido pelo usuário.

Em resumo, as transações GeneXus realizam automaticamente os seguintes controles:. Integridade referencial. Unicidade de chave (tanto primária como candidatas)

Page 77: 93909254 GENEXUS Heuristica Apostila Teorica

77

• São criados automaticamente, sob certas condições, quando são necessários, e são eliminados quando termina a execução do objeto que os criou.

• Se deseja acessar os dados ordenados por determinados atributos,mas não se deseja criar um índice permanente para ele: GeneXus cria um índice temporário.

• Em algumas plataformas, as consultas para as quais se quer obtero resultado ordenado por determinados atributos, e não existe o índice de usuário, são resolvidos pelo DBMS correspondente sem a criação de índices temporários.

• O usuário pode resolver deixar de utilizar um índice temporário, criando um índice de usuário.

Integridade ReferencialÍndices Temporários

ÍNDICES TEMPORÁRIOS

Quando se deseja acessar os dados ordenados por determinados atributos, mas não se deseja criar um índice permanente para ele (por exemplo, porque se trata de uma consulta que se realiza com pouca freqüência), então, dependendo da plataforma, um índice temporário é criado.

Page 78: 93909254 GENEXUS Heuristica Apostila Teorica

78

• Para cada atributo não inferido, e que não seja o identificador na estrutura de uma transação, é possível definir para a tabela associada se vai ser nulo ou não

Integridade ReferencialGerência de nulos

A permissão ou não do valor <NULL> na base de dados é muito importante no modelo relacional. Permitir o valor null para um atributo dado, significa que pode em certas circunstâncias, ser “ignorado” visto que é “valor não especificado”. Por outro lado, o atributo não permitindo valor null, um valor válido deve sempre ser atribuído a ele.

A propriedade Nulls (apresentada como coluna no editor de estrutura de transações), permite configurar para cada atributo se admite ou não valor null na tabela associada. Os atributos que podem ser configurados desta forma, são aqueles armazenados nas tabelas associadas na transação (isto é, não inferidos) sempre e quando não forem atributos primários nestas tabelas (já que por definição as chaves primárias não suportam valor null).

Resumindo: o objetivo desta propriedade é definir qual valor vai ser armazenado na base de dados quando não for digitado nada no campo (o valor <NULL> ou o valor empty).

Page 79: 93909254 GENEXUS Heuristica Apostila Teorica

79

• A propriedade Nulls aceita os seguintes valores:- No: Valor por default. O atributo na tabela associada, não

permitirá valor null- Yes: o atributo na tabela associada, admitirá valor null

• Atributos que fazem parte da chave primária não suportam valor null (propriedade Nulls = No, sempre)

• Atributos da chave estrangeira aceitam nulo e isto repercute noscontroles de integridade referencial.

Integridade ReferencialGerência de nulos

Os valores possíveis de serem configurados para essa propriedade Nulls são:

No: significa que o atributo não permite o valor null na tabela associada (valor por default) Yes: significa que o atributo permite o valor null na tabela associada.

A definição de nulls é utilizada por GeneXus no momento de criar/reorganizar as tabelas da base de dados, já que o suporte ou não suporte de nulabilidade dos atributos em sua tabela, se define a nível da base de dados.

Ou seja que modificar o valor da propriedade Nulls para um atributo vai implicar em executar uma reorganização (para redefinir a nível da base de dados o suporte de nulabilidade do atributo em sua tabela).

Page 80: 93909254 GENEXUS Heuristica Apostila Teorica

80

• Repercussão em controles de integridade referencial

1) CountryId e CityId com propriedade Nulls=No

• As checagens de IR mostradas acima são realizadas

2) CityId com propriedade Nulls=Yes

• Um controle de IR em CUSTOMER é agreagado � se deixar nulo CityId, realiza checagem contra COUNTRY.

CountryId*CountryName

CountryId*CityId*CityName

CustomerId*CustomerNameCountryIdCityId

FK composta

Integridade ReferencialGerência de nulos

Repercussão em controles de integridade referencial

A definição de nulls para atributos que formam uma chave estrangeira diz ao GeneXus quão forte é a referência a outra tabela.

Se nenhuns dos atributos que compõem uma chave estrangeira permitem valores nulos (caso 1), trata-se de uma referência forte (também conhecida como “not null reference”), já que é estabelecido que a FK deverá sempre apontar a um registro existente da tabela referenciada.

Outro caso, é se uma chave estrangeira que tenha pelo menos um atributo que suporte nulos (caso 2), se estabelece uma referência fraca (também conhecida como “null reference”), já que se algum dos atributos que formam parte da chave estrangeira são nulls, então a referência não será checada.

Quando uma chave estrangeira é composta e os nulos são permitidos para alguns de seus atributos, podem aparecer novas referencias (não checadas caso possua referências fortes) se os atributos restantes compõem também uma chave estrangeira. Um exemplo é o apresentado acima, onde se o usuário deixar nulo o valor de CityId

para um cliente, se realizará a checagem de IR contra COUNTRY, para assegurar que o país ingressado esteja correto.

Page 81: 93909254 GENEXUS Heuristica Apostila Teorica

81

• Diferença entre valor empty e null para atributos:

• empty: é um valor (0 para Numeric, “” para Character, etc.)

• null: se é permitido, não é um valor. Significa que o valor deve ser considerado como:

• não especificado• não disponível• não atribuído• desconhecido

• Métodos segundo se o atributo permite null ou empty:

• IsEmpty• IsNull• SetEmpty• SetNull

Integridade ReferencialGerência de nulos

Métodos para trabalhar com nulos e vazios

IsEmpty, IsNull: devolvem true quando o atributo contem valor empty ou null respectivamente.

SetEmpty, SetNull: configuram no atributo o valor empty ou null, respectivamente.

Exemplos:

* error(‘You must specify a name’) if CustomerName.IsEmpty();

* msg(‘Warning: You didn’t specify a Country’) if ContryId.IsNull();

Page 82: 93909254 GENEXUS Heuristica Apostila Teorica

82

TABELA BASEE

TABELA ESTENDIDA

Page 83: 93909254 GENEXUS Heuristica Apostila Teorica

83

Os critérios de normalização do desenho da base de dados servem para minimizar a possibilidade de inconsistência dos dados. Uma base de dados desenhada desta maneira tem uma série de vantagens importantes (tanto é assim que atualmente a normalização de dados é um padrão de desenho), mas que deve ser considerado também alguns inconvenientes.

O inconveniente mais notório é que os dados se encontram dispersos em muitas tabelas, e muitas vezes quando se quer realizar consultas mais ou menos complexas à base de dados, devemos consultar uma quantidade importante de tabelas.

Assim, por exemplo, se o seguinte Diagrama representa nosso modelo de dados:

para listar as faturas seria necessário consultar as tabelas: INVOICE e INVOICEDETAIL (linhas de faturas), CUSTOMER, COUNTRY e PRODUCT.

Para simplificar esta tarefa GeneXus utiliza o conceito de tabela estendida.

Chamamos tabela base a qualquer tabela da base de dados na qual estamos posicionadosem determinado momento; e dada certa tabela base, sua tabela estendida alcançará todos os atributos da própria tabela base, mas todos os atributos das tabelas que tenham informação relacionada unicamente com a tabela base (relação N-1 desde a tabela base, direta e indiretamente).

Page 84: 93909254 GENEXUS Heuristica Apostila Teorica

84

INVOICE CUSTOMER COUNTRY

INVOICEDETAIL PRODUCT

InvoiceId*InvoiceDateCustomerId

CustomerId*CustomerNameCountryId

CountryId*CountryName

InvoiceId*ProductId* InvoiceLineQuantityInvoiceLineAmount

ProductId*ProductDescriptionProductPriceProductStock

Tabela Base e Tabela Estendida

Utilizando o diagrama é fácil determinar qual é a tabela estendida correspondente a uma tabela base qualquer:

Partindo da tabela base, devem-se seguir as relações N-1 (devem-se seguir as setas que tem ponta dupla partindo da tabela base e ponta simples no outro extremo).

Todas as tabelas as quais se pode chegar seguindo as setas que representam relações N-1 da tabela base, formaram parte de sua tabela estendida.

O seguinte quadro mostra a tabela estendida correspondente a cada uma das tabelas de nosso modelo de dados:

Page 85: 93909254 GENEXUS Heuristica Apostila Teorica

85

• São utilizadas para definir o comportamento das transações.• Algumas regras:

• Podem incluir: atributos, variáveis, constantes e funções.• São LOCAIS a transação.• Programação DECLARATIVA.

� Default� Atribuição� Msg� Error� Noaccept� Add� Subtract� Serial� Update

Regras

No objeto transação as regras cumprem um rol muito importante, já que permitem programar seu comportamento (por exemplo: atribuir valores por default, definir controles sobre os dados, etc.).

São escritas de forma declarativa, ou seja, a ordem em que se escreve não significa a ordem de execução.

Podem envolver os atributos definidos na estrutura da transação¹, assim como as variáveis definidas dentro do objeto, constantes e funções.

Somente são válidas dentro da transação na qual estão definidas, ou seja, são locais.

___________________________________________________________________________

1 Todas as regras das transações podem utilizar atributos das tabelas base associadas a transação; e a maior parte delas pode também utilizar atributos das tabelas estendidas de ditas tabelas base. Para um atributo poder ser referenciado em regra, o mesmo deve estar incluído na estrutura da transação (seja que pertença a alguma das tabelas base associadas da transação ou as suas tabelas estendidas).

Page 86: 93909254 GENEXUS Heuristica Apostila Teorica

86

Algumas regras válidas para transação são:

Default

OBJETIVO: Permite atribuir um valor por default para um atributo ou variável; o valor por default inicialiaza o atributo ou a variável quando está sendo realizada uma inserção através da transação (modo Insert), mas o usuário final pode alterar esse valor se não for o desejado.

SINTAXE: Default( att | &var, exp );

ONDE:• att: é um atributo que pertence a alguma das tabelas base associadas na transação.• var: é o nome de uma variável.• exp: é uma expressão que pode envolver constantes, funções, variáveis ou outros atributos.

FUNCIONALIDADE: Esta regra atribui o valor da expressão exp como valor por default do atributo att ou variável var, quando a transação é executada em modo Insert.

Esta regra não é válida para atributos que formam parte da chave primária de algum dos níveis da transação, porque é disparada logo que a chave é informada (já que somente nesse momento o modo éconhecido e esta regra é disparada somente em modo Insert

EXEMPLOS: Default( InvoiceDate, &today ); /* Regra definida na transação “Invoice” */

Quando uma Invoice nova é inserida, se sugere o valor de InvoiceDate o valor contido na variável do sistema &today.

Default( InvoiceDate, Today()); /* Regra definida na transação “Invoice” */

Análoga a anterior, a diferença é que ao invés de utilizar a variável do sistema today, se utiliza a função Today que devolve a data correspondente ao dia.

Default( InvoiceLineAmount, ProductPrice*InvoiceLineQuantity); /* Regra definida na transação “Invoice” */

Quando uma linha da fatura é inserida, se sugere que o atributo InvoiceLineAmount (valor da linha) receba o valor resultante da expressão ProductPrice*InvoiceLineQuantity (preço do produto vezes a quantidade levada do mesmo).

Nota: O tipo de dados da expressão deve coincidir com o tipo de dados do atributo ou variável.

Regra de atribuição

OBJETIVO: Permite atribuir a um atributo ou a uma variável, o valor de uma expressão.

SINTAXE: att | &var = exp [if cond] [on evento / momento de disparo];

ONDE: • att: é um atributo que pertence alguma das tabelas base associadas a transação, ou a suas estendidas (deve estar declarado na estrutura).• var: é o nome de uma variável.• exp: é uma expressão que pode envolver constantes, funções, variáveis ou outros atributos, e deve ser do mesmo tipo que att ou var.• cond: é uma expressão booleana (pode conter os operadores lógicos and, or, not)• evento/momento de disparo: é um dos eventos predefinidos do GeneXus disponíveis para regras de transações, que permitem definir o momento específico de execução de uma regra.

FUNCIONALIDADE: Uma regra deste tipo permite atribuir ao atributo ou variável que fica a esquerda, o valor resultante da expressão. Como se pode ver, a condição é opcional; se ela não for definida, a atribuição érealizada sempre.

A atribuição a um atributo, implica sua atualização no registro que corresponda. A atribuição a um atributo, implica em sua atualização no registro que corresponda. As regras de atribuição podem ser definidas aos atributos de alguma das tabelas bases associadas a transação, incluso de suas estendidas. Isto significa que os atributos inferidos podem ser atualizados em uma transação (sendo necessário os declarar na estrutura).

Page 87: 93909254 GENEXUS Heuristica Apostila Teorica

87

EXEMPLO:

InvoiceLineAmount = ProductPrice * InvoiceLineQuantity; /* Regra definida na transação “Invoice” */

Se o valor de cada linha de uma fatura é calculado sempre multiplicando o preço do produto vezes a quantidade levada do mesmo, podemos utilizar esta regra de atribuição para que o usuário não precise realizar o cálculo.

Error

OBJETIVO: Permite mostrar uma mensagem de erro se a condição seja satisfeita. Serve para definir os controles que os dados devem cumprir.

SINTAXE: Error( ‘msg’ | &var | character expresion, msgId ) if cond [on evento/momento de disparo];

ONDE: • msg: é uma string com uma mensagem de error a mostrar• var: é o nome de uma variável de tipo caractere, que contêm uma string com uma mensagem de erro a mostrar•character expression: é uma expressão cujo tipo resultante, é caractere e que será mostrada•msgId: é uma string (sem espaços em branco nem aspas) que será utilizado somente se a transação é definida também como business component1.•cond: tipo booleana (que pode conter os operadores lógicos and, or, not)•evento/momento de disparo: é um dos eventos pré-definidos do GeneXus disponíveis para regras de transações, que permitem definir o momento específico da execução de uma regra.

FUNCIONALIDADE: Esta regra mostra a mensagem do parâmetro msg, var ou expressão caractere, se a condição cond avaliada resulta como verdadeira. A mensagem de erro aparece em uma tela pop-up quando o ambiente de trabalho é Windows e no controle Error Viewer e/ou um quadro texto quando o ambiente de trabalho é Web, detendo qualquer atualização na base de dados. Quando a transação é executado como business component (estudaremos este tema mais adiante), ao disparar o error, gera um entrada no SDT messages, com identificador msgId.

EXEMPLOS:

Error(‘Informe o Nome do Cliente’) if CustomerName.isEmpty();/*Regra definida na transação “Customer”*/

Se avalia a condição CustomerName.isEmpty(), e se for satisfeita, mostra a mensagem ‘Informe o Nome do Cliente’ na tela. Não permite continuar até que o usuário ingresse um nome no campo CustomerName ou abandone a transação (nesse caso não é realizada nenhuma atualização na base de dados).

Error(‘Fatura não pode ser eliminada’) if Delete;/* Regra definida em a transação “Invoice” */

Necessita proibir a eliminação de faturas. Com esta regra, se o usuário tentar realizar uma eliminação, a condição dará True e se dispara a regra, evitando a eliminação.

MsgOBJETIVO: Permite mostrar uma mensagem de advertência se a condição for satisfeita

SINTAXE: Msg( ‘msg’ | &var | character expresion, msgId) if cond [on evento/momento de disparo];

ONDE:msg, var, character expresion, msgId, cond, evento/momento de disparo: são os mesmos que para a regra error.Observar que a sintaxe é exatamente a mesma.

FUNCIONALIDADE: Esta regra se utiliza para apresentar mensagens de advertência ao usuário. Mostra a mensagem do primeiro parâmetro, se a condição é satisfeita, analogamente a regra Error; mas a diferença desta última, permite continuar com a execução se a condição segue sendo satisfeita. Do mesmo modo, se a transação é business component1, se disparar a regra gera entrada no SDT messages.As mensagens de advertência são mostradas no Error Viewer.__________________________________________________________________________________________1 Este tema será visto mais adiante no curso.

Page 88: 93909254 GENEXUS Heuristica Apostila Teorica

88

EXEMPLO:

Msg( ‘Nome do Cliente não foi informado’ ) if CustomerName.isEmpty();/*Regra definida na transação "Customer”*/

Se avalia a condição CustomerName.isEmpty(), e se esta se satisfaz mostra-se a mensagem ‘Nome do Cliente não foi informado’. A diferença que ocorre com a regra Error, é que aqui é permitido continuar a execução, pois não se trata de um erro e sim de uma advertência.

Noaccept

OBJETIVO: Permite indicar que o atributo não aceite valores por parte do usuário (será somente de saída).

SINTAXE: Noaccept(att) [if cond] [on evento/momento de disparo];

ONDE: att: é um atributo pertencente a alguma(s) da(s) tabela(s) base(s) associada(s) à transaçãocond: é uma expressão booleana (pode conter os operadores lógicos and, or, not)Evento/momento de disparo: é um dos eventos predefinidos pelo GeneXus disponíveis para regras de transações, que permitem definir o momento específico de execução de uma regra.

FUNCIONALIDADE: em uma transação, todos os atributos que pertencem as tabelas base associadas a transação, por default são aceitos. Se quisermos que um atributo destas características não seja aceito, então contamos com a regra Noaccept.

EXEMPLO: Noaccept( InvoiceDate) if Update; /* Regra definida na transação “Invoice” */

Se está modificando uma fatura (modo Update), não é permitido que seja modificada sua data.

Subtract

OBJETIVO: Subtrai o valor de um atributo ao valor de outro atributo, se satisfaz a condição especificada.

SINTAXE: subtract(att1, att2) [if cond];

ONDE:att1, att2: são atributos pertencentes a alguma das tabelas base associadas à transação, ou a suas tabelas estendidas (e devem estar declarados na estrutura).cond: é uma expressão booleana (que pode conter os operadores lógicos and, or, not).

FUNCIONALIDADE: A subtração é realizada levando em consideração o modo que se esteja trabalhando na transação (Insert, Update ou Delete). Em modo:

- Insert: subtrai o valor do atributo att2, o valor do atributo att1- Delete: soma a valor de att2, o valor do atributo att1- Update: subtrai o valor do atributo att2, a diferença entre o valor novo e o velho do att1

EXEMPLO:

Na transação “Invoice”, cada vez que se ingressa uma linha com um produto que se está comprando, se deve diminuir o stock do mesmo, segundo a quantidade levada.

Isto poderia ser feito de forma simples com a seguinte regra de atribuição:

ProductStock = ProductStock – InvoiceLineQuantity;

Se prestarmos atenção, todavia, vemos que esta regra não nos serve, pois não está condicionada a um modo particular, razão pelo qual será disparada tanto quando estiver inserindo uma nova linha na fatura, como quando se está eliminando ou modificando uma já existente. Nestes últimos dois casos é incorreto disparar a regra.

Page 89: 93909254 GENEXUS Heuristica Apostila Teorica

89

De fato, quando é eliminada uma linha existente, a operação contrária deve ser realizada, ou seja, “devolver” ao estoque o que havia sido quitado quando se inseriu a linha.

O correto então, tendo em conta todos os casos possíveis seria ter 3 regras:

ProductStock =ProductStock - InvoiceLineQuantity if Insert;ProductStock =ProductStock + InvoiceLineQuantity if Delete;ProductStock=ProductStock + old(InvoiceLineQuantity) – InvoiceLineQuantity if Update;

Aqui estamos utilizando a função “old”, que devolve o valor armazenado do atributo (é o valor antes de modificá-lo). Para evitar fazer tudo GeneXus fornece a regra subtract que se encarrega de fazer a atribuição correta de acordo ao modo. Então podemos substituir as 3 atribuições anteriores, por:

subtract( InvoiceLineQuantity, ProductStock);

Esta regra tem a inteligência para, dependendo do modo, subtrair ou somar,

Add

OBJETIVO: Soma o valor de um atributo ao valor de outro atributo, se a condição especificada for satisfeita.

SINTAXE: add( att1, att2) [if cond];

ONDE:att1, att2 : são os atributos pertencentes a alguma das tabelas base associadas a transação, ou a suas estendidas (e devem estar declarados na estrutura).cond: é uma expressão booleana.

FUNCIONALIDADE: a adição é realizada considerando o modo da transação (Insert, Update ou Delete). Modo:

- Insert: soma ao valor do atributo att2, o valor do atributo att1- Delete: subtrai ao valor de att2, o valor do atributo att1- Update: soma ao valor do atributo att2, a diferença entre o valor novo e o velho de att1

EXEMPLO:Definimos na transação "Customer", um atributo de nome CustomerTotalPurchases, para registrar o valor total de compras efetuadas pelo mesmo. O comportamento desejado é que cada vez que for criado uma fatura para um cliente, seja somado o total da fatura (InvoiceTotal) ao total de compras efetuadas pelo cliente (CustomerTotalPurchases).

Como vimos na regra subtract, não devemos esquecer que na transação “Invoice” podemos também eliminar e modificar Invoice, e não somente criá-las; para tanto é importante ter em conta o modo de trabalho na transação (Insert, Update, Delete). O GeneXus nos libera de termos que considerar os modos, tendo que escrever as seguintes 3 regras de atribuição na transação “Invoice” :

CustomerTotalPurchases = CustomerTotalPurchases + InvoiceTotal if Insert;CustomerTotalPurchases = CustomerTotalPurchases – InvoiceTotal if Delete;CustomerTotalPurchases = CustomerTotalPurchases – old(InvoiceTotal) + InvoiceTotal if

Update;

Ao invés disso o GeneXus nos brinda com a regra add, que encarrega de somar ou diminuir, dependendo do modo.

Page 90: 93909254 GENEXUS Heuristica Apostila Teorica

90

Se agregarmos na transação "Customer“ o atributo CustomerTotalPurchases (total de compras do cliente):

CustomerId*CustomerNameCustomerAddressCustomerGender...CustomerTotalPurchases

E na transação “Invoice” inferimos o atributo CustomerTotalPurchases – que pertence a tabela estendida -, podemos definir a regra:

add(InvoiceTotal, CustomerTotalPurchases);

E conseguimos o comportamento desejado, que é:

• se insere uma fatura (Insert): soma ao valor do atributo CustomerTotalPurchases, o valor do atributo InvoiceTotal• se elimina uma fatura (Delete): subtrai ao valor do atributo CustomerTotalPurchases, o valor do atributo InvoiceTotal• se modifica uma fatura (Update): soma ao valor do atributo CustomerTotalPurchases, a diferença entre o valor novo e o velho de InvoiceTotal

Serial

OBJETIVO: Permite serializar (auto-numerar) atributos numéricos.

SINTAXE: Serial( att1, att2, step);

ONDE:att1 : é um atributo pertencente a alguma das tabelas base associadas à transação (isto é,não inferido), que deseja serializar (depende de estar declarado na estrutura).att2 : deve pertencer a uma tabela diretamente superordinada à do atributo att1.step: é o passo ou incremento da serialização

FUNCIONALIDADE: o propósito desta regra é atribuir um número correlativo à att1 cada vez que éinserido um registro na tabela que pertence att1. Toma-se o valor de att2 att2 contém o último número utilizado na auto-numeração), incrementa-se o valor do parâmetro step, e o valor resultante é atribuído tanto ao atributo att1 do novo registro, como ao atributo att2 para conservar o último número atribuído.

Quando um registro é inserido por meio de uma transação na qual foi definida a regra: Serial (att1, att2, step), se acesse ao att2 (haverá um só valor deste atributo relacionado, pois pertence a uma tabela diretamente superordinada), soma-se o valor step, e se atribui o valor obtido tanto a att1 do registro que vai inserir, como a att2 pertencente a uma tabela diretamente superordinada com respeito à tabela que contem a att1.

Desenha a transação "Invoice" contendo um Número de linha de Invoice (atributo InvoiceLineId) como identificador único do segundo nível. A estrutura da transação seria:

INVOICE{

InvoiceId*CustomerIdCustomerNameInvoiceDateInvoiceLastLineId

INVOICEDETAIL{

InvoiceLineId*ProductIdProductDescription……

}}

Page 91: 93909254 GENEXUS Heuristica Apostila Teorica

91

Neste desenho o atributo ProductId não é o identificador único do nível, e sim a chave estrangeira unicamente.

Cada linha tem um número de linha que é identificada de forma única, é possível ingressar o mesmo produto em distintas linhas.

Pode ser útil atribuir por meio do sistema, números correlativos ao campo InvoiceLineId, definindo a regra:

Serial (InvoiceLineId, InvoiceLastLineId, 1);

O primeiro parâmetro da regra serial define qual é o atributo a ser numerado automaticamente, no segundo parâmetro deve ser indicado um atributo cuja função é guardar o último valor atribuído até o momento, e por último o terceiro parâmetro é para indicar o incremento (neste caso se incrementa de um em um).

O segundo parâmetro (no exemplo InvoiceLastLineId) deve pertencer a uma tabela diretamente superordinada à tabela que contém o atributo que se deseja numerar automaticamente (InvoiceLineId). A regra serial o requer assim. No exemplo, pode ser observado que InvoiceLastLineId encontra-se na tabela de chave InvoiceId*, a qual é diretamente superordinada à tabela que contém o atributo à numerar (InvoiceLineId).

Isto é, cada fatura terá no cabeçalho, um atributo que armazena o último número de linha atribuído até o momento (InvoiceLastLineId). A regra serial está implementada de forma que necessita deste atributo (para fixar o último número utilizado, somá-lo ou incremento, e atribuir o próximo número da nova linha).

Consideração:A regra serial é útil na hora de auto-numerar (serializar) linhas, não em cabeçalhos (por exemplo, números de faturas, números de clientes, etc.). Para utilizá-la precisa definir um atributo em uma tabela diretamente superordinada; isto resulta que se desejarmos auto-numerar linhas devemos incluir este atributo no nível da estrutura imediatamente superior ao do atributo a serializar.

Page 92: 93909254 GENEXUS Heuristica Apostila Teorica

92

Contamos com uma solução muito mais simples para autonumerar cabeçalhos: quando uma tabela tem uma chave simples (é formada por somente um atributo) e o tipo de dados é numérico, pode numerar-se automaticamente utilizando a funcionalidade que fornecem os administradores de base de dados para isto. A forma de indicá-lo em GeneXus éconfigurando a propriedade Autonumber do atributo chave:

Se na propriedade Autonumber de um atributo numérico chave, selecionar o valor True, significa que será realizada a numeração automática do mesmo. Serão agregadas as seguintes propriedades no diálogo:

Start: Mediante esta propriedade se configura a partir de qual número começa a numeração automática.

Step: Mediante esta propriedade é possível configurar o incremento do campo (entre dois registros).

For replication: Esta propriedade é somente válida para o motor de base de dados SQL Server; o valor Yes indica a este que não deve aplicar a propriedade em caso de que a tabela seja receptora de replicação (mas que deve manter os números vindos da replicação).

Para maiores detalhes desta propriedade, recomendamos acessar ao Help de GeneXus.

Page 93: 93909254 GENEXUS Heuristica Apostila Teorica

93

Update

OBJETIVO: Possibilita atualizar no form de uma transação (Win/Web) atributos da tabela estendida (inferidos).

SINTAXE: Update( att1[, atti …]);

ONDE:atti: é um atributo pertencente a tabela estendida de alguma das tabelas bases associadas a transação.

FUNCIONALIDADE: Em uma transação, todos os atributos que pertencem as tabelas associadas a transação, por default são aceitos e os que pertencem a tabela estendida, não pertencem a base, são inferidos, e portanto não aceitos.

Mas se queremos que estes atributos inferidos sejam aceitos, para que o usuário possa modificar a partir do form seu valor, então temos a regra Update.

EXEMPLO:

InvoiceId*InvoiceDateCustomerIdCustomerName…

CustomerId*CustomerName…

update(CustomerName);

Page 94: 93909254 GENEXUS Heuristica Apostila Teorica

94

• Em qual nível de uma transação são executadas as regras definidas na mesma?

• Como condicionar regras para que sejam executadas em determinados modos?

RegrasConceitos importantes

Em qual nível de uma transação são executadas as regras definidas na mesma?

Na maioria das vezes não é necessário agregar explicitamente na definição das regras o nível da transação no qual se deseja que sejam disparadas, já que os atributos envolvidos nas regras guiam GeneXus ao nível correspondente para executá-las.Por exemplo, se uma regra referencia unicamente a atributos do primeiro nível da transação na qual se encontra definida (seja na própria regra ou na condição de disparo), GeneXus entende que a mesma estará associada ao primeiro nível da transação. Analogamente, se uma regra referencia somente atributos do segundo nível da transação na qual está definida (seja na própria regra ou na condição de disparo), GeneXus entende que a mesma estará associada ao segundo nível da transação.

No caso que uma regra referencie atributos de vários níveis, GeneXus entende que a regra estáassociada ao último dos níveis dos atributos envolvidos, já que será no último nível que terá os valores de todos os atributos implicados.

Em seguida apresentaremos exemplos concretos:

1) Se define a seguinte regra na transação “Invoice”:Default(InvoiceDate, &today);

como o único atributo que se menciona na regra é InvoiceDate, e é um atributo do primeiro nível da transação, GeneXus determina que se trata de uma regra associada ao primeiro nível.

2) Se definir a seguinte regra na transação “Invoice”:subtract( InvoiceLineQuantity, ProductStock );

como os dois atributos mencionados na mesma se encontram no segundo nível da transação, GeneXus determina que se trata de uma regra associada ao segundo nível.

Page 95: 93909254 GENEXUS Heuristica Apostila Teorica

95

3) Se definir a seguinte regra na transação “Invoice”: InvoiceLineDiscount= InvoiceLineAmount * CustomerDiscountPercentage/100;

sendo InvoiceLineDiscount (desconto correspondente a uma linha) um atributo pertencente ao segundo nível da transação “Invoice” e CustomerDiscountPercentage (porcentagem de desconto ortogado a um cliente) um atributo declarado no primeiro nível da transação “Invoice”, GeneXus determina que se trata de uma regra associada ao segundo nível da transação.

Quando nos referimos que uma regra está associada a determinado nível, significa que a mesma se executa para cada instancia com a qual se trabalhe através desse nível (se cumprir com a condição de disparo da regra).

No caso do primeiro exemplo visto, a regra Default(InvoiceDate, &today) é uma regra associada ao primeiro nível da transação “Invoice”. Isto significa que ao executar todo cabeçalho de fatura inserido através do primeiro nível da transação “Invoice” (a regra Default tem a particularidade de se disparar unicamente quando o modo de execução é Insert).

No caso do segundo exemplo visto, a regra subtract(InvoiceLineQuantity, ProductStock) é uma regra associada ao segundo nível da transação “Invoice”. Isto significa que executando toda linha da fatura que se insira, atualize ou elimine através do segundo nível da transação “Invoice”.

No caso do terceiro exemplo, a regra:InvoiceLineDiscount = InvoiceLineAmount * CustomerDiscountPercentage/100 é uma regra associada ao segundo nível da transação “Invoice”. De modo que esta regra se executa para toda linha da fatura que se insira, atualize ou elimine através do segundo nível da transação “Invoice”.

Concluindo, para cada fatura com a qual se trabalhe através da transação “Invoice”:- para o cabeçalho: são executadas as regras associadas ao primeiro nível - para cada uma das linhas: são executadas as regras associadas ao segundo nível

É importante saber que como norma geral GeneXus sempre determina que uma regra seja disparada no primeiro momento possível, isto é, naquele momento que tenha todos os dados necessários. E somente em alguns casos que assim o requeiram, a mesma regra voltará a ser disparada mais adiante.

Qual nível de disparo por default é associado uma regra que não referencia atributos?

Quando não tem atributos envolvidos numa regra, o nível associado por default a regra será o primeiro.

Por exemplo, a seguinte regra definida na transação “Invoice”:Error(‘Faturas não podem ser eliminadas’) if Delete;

não tem atributos envolvidos, portanto, o nível associado por default a regra será o primeiro.

Quando tem que especificar explicitamente o nível de disparo de uma regra?

Existe uma cláusula opcional de nome Level que permite modificar o nível por default de disparo de uma regra, alterando-o por um nível posterior.

Isto é, se por exemplo uma regra se executa por default para o primeiro nível de uma transação e se deseja que se execute para o segundo, se deverá agregar a regra ou componente Level seguido de um atributo ou conjunto de atributos do segundo nível. Isto fará que a regra se execute para cada uma das instancias correspondentes as linhas, e não para a instancia correspondente ao cabeçalho como era o comportamento por default.

Por exemplo, se definimos a seguinte regra na transação “Invoice”:

msg(‘A data da fatura é maior que a data atual’) if InvoiceDate > &Today;

por default esta regra está associada ao primeiro nível da transação, já que o único atributo referenciado na regra se encontra no primeiro nível da transação. Se por algum motivo desejamos que a regra se execute para cada uma das instancias correspondentes as linhas em vez de executar-se para a instancia correspondente ao cabeçalho, teremos que agregar na definição da regra, a cláusula Level seguida de um ou vários atributos do segundo nível:

msg(‘A data da fatura é maior que a data atual’) if InvoiceDate>&Today Level InvoiceLineAmount;

Page 96: 93909254 GENEXUS Heuristica Apostila Teorica

96

Agregar a cláusula Level a uma regra somente faz sentido se a continuação da mesma são mencionados atributos que são de algum nível posterior aos níveis dos atributos implicados na definição da regra em si.

No seguinte exemplo, o fato de ter agregado a cláusula Level a regra não agrega mais informação visto que o atributo que já tem essa informação na definição da própria regra:

msg(‘A data da fatura é maior que a data atual’) if InvoiceDate > &Today Level CustomerId;

É fácil compreender que o atributo InvoiceDate já guia GeneXus que se trata de uma regra associada ao primeiro nível, assim que o especificado pela cláusula Level no exemplo não contribui mais informação e portanto é desnecessário.

Por último, no exemplo que segue:

InvoiceLineDiscount= InvoiceLineAmount * CustomerDiscountPercentage/100 Level InvoiceDate;

se incluiu a cláusula Level na definição da regra, como o atributo que segue a cláusula é de um nível superior ao nível dos atributos referenciados na regra, a cláusula Level definida não contribuiu com informação útil neste caso. Isto é, não é possível que possuindo atributos envolvidos de um segundo nível em uma regra, a mesma se execute no primeiro nível, já que no primeiro nível não tem informação do ou dos níveis inferiores (além de que tem N instancias para os níveis inferiores). De modo que a regra seguirá estando associada ao segundo nível da transação “Invoice”, não contribuindo com informação útil da cláusula Level neste exemplo.

Concluindo, a cláusula Level somente faz sentido que seja agregada para modificar o nível por default de disparo de uma regra, a um nível posterior.

Como condicionar regras para que se executem em determinados modos?

GeneXus fornece as seguintes funções booleanas para poder incluí-las na condição de disparo das regras com o objetivo de limitá-las que se executem pontualmente em alguns dos modos possíveis:

• Insert• Update• Delete

Exemplos de uso (todas as regras correspondem a transação “Invoice”)

1) Noaccept( InvoiceDate ) if Update;

Se está modificando uma fatura (modo Update), não se permite que sua data seja modificada. Se a regra foi definida sem condição de disparo que temos explicitado, o atributo InvoiceDate fica desabilitado em todos os modos de execução.

2) Error( ‘Faturas não podem ser eliminadas’ ) if Delete;

Se tentar eliminar uma fatura, se dispara o error impedindo a eliminação. Como não tem atributos envolvidos na regra, por default o nível associado a regra será o primeiro.

3) Error( ‘Linhas da Faturas não podem ser eliminadas’ ) if Delete Level InvoiceLineQuantity;

Se tenta eliminar uma linha de uma fatura, se dispara o error impedindo a eliminação. Observar que se tem explícito na regra a cláusula Level seguida de um atributo do segundo nível da transação “Invoice”, para indicar que se deseja que a mesma esteja associada ao segundo nível da transação.

Page 97: 93909254 GENEXUS Heuristica Apostila Teorica

97

Fórmulas

Page 98: 93909254 GENEXUS Heuristica Apostila Teorica

98

• Definir fórmulas possibilita compartilhar conhecimento e obter código gerado otimizado

• Quando o valor de um atributo ou variável pode ser calculado a partir de outros atributos, constantes e/ou funções, pode ser definida como uma fórmula

• Contamos com 2 formas de definir fórmulas:

- Globais: A nível da Base de Conhecimento- Locais: Entre certo código

Veremos este conceito emprimeiro lugar

Veremos este conceito mais adiante com mais conhecimento GeneXus

FórmulasObjetivos e Definição

Quando definirmos uma fórmula, GeneXus pode combinar a consulta / cálculo associada a fórmula com a consulta na qual a fórmula está presente e assim gerar sentenças otimizadas.

Page 99: 93909254 GENEXUS Heuristica Apostila Teorica

99

• Fórmula Global = atributo onde o analista GeneXus atribui um cálculo associado

• Somente atributos podem ser definidos como fórmulas globais, variáveis não podem

• Como é a realizada a definição?

FórmulasGlobais

Acessando o editor de fórmulas a partir da estrutura da transação �

Page 100: 93909254 GENEXUS Heuristica Apostila Teorica

100

• Dizemos que:

• Significando que:

- Não são criados como atributos físicos

- Para cada objeto que referencie um atributo fórmula global, GeneXus incluirá em seu programa gerado o código necessário para realizar o cálculo e mostrá-lo em tempo de execução

• Tabela base / Tabela associada a um atributo fórmula global:

- Tabela na qual o atributo seria armazenado se não fosse fórmula

FórmulasGlobais

atributos fórmulas globais = atributos virtuais

Como explicamos neste slide, os atributos definidos como fórmula global, não são criados como campos físico em tabelas, dizemos que são atributos virtuais.

Todavia, dizemos que tem uma tabela “associada” ou tabela “base”, para conhecer o contexto na qual foi definida, e contar com esse contexto do momento de disparar o cálculo correspondente onde for referenciado.

Page 101: 93909254 GENEXUS Heuristica Apostila Teorica

101

FórmulasClassificação

• Horizontais: Uma ou várias expressões aritméticas

• Aggregate: Sum, Count, Average, Max, Min, Find

• Compostas: Conjunto de expressões Horizontais e/ou Aggregate

• Importante:

- Quando definirmos fórmulas no GeneXus não indicamos a classificação

- A classificação é externa ao GeneXus e sua finalidade é agrupar fórmulas por:

� Tipo de cálculo oferecido� Atributos que podem ser envolvidos na sua definição

TODAS PERMITEM INCLUIR CONDIÇÃO DE DISPARO

PODE SER GLOBAIS E LOCAIS

Page 102: 93909254 GENEXUS Heuristica Apostila Teorica

102

FórmulasClassificação

• Exemplo de Fórmula Horizontal (Global) :

CustomerTotalPurchases – CustomerTotalPayments

{ CustomerId*CustomerNameCustomerTotalPurchasesCustomerTotalPaymentsCustomerBalance}

Customer

TABELA CUSTOMER

CustomerId*CustomerNameCustomerTotalPurchasesCustomerTotalPayments

DEIXA DE PERTENCER FISICAMENTE A TABELA

Na definição de um atributo como fórmula horizontal, é possível envolver atributos pertencentes a tabela associada ao atributo que a fórmula está sendo definida e a sua tabela estendida.

No exemplo, ao definir que o atributo CustomerBalance é fórmula, o mesmo deixará de existir como campo físico da tabela CUSTOMER.

Diremos a partir desse momento CustomerBalance é um atributo virtual e que sua tabela “base ou associada” seráCUSTOMER, já que se fosse armazenar dito atributo novamente (seja porque o analista definiu que deixa de ser fórmula ou que é fórmula redundante) seria criado como atributo físico na tabela CUSTOMER.

O tipo de cálculo desta fórmula definida é horizontal, já que consiste em uma expressão aritmética; portanto os atributos que podem ser referenciado na definição desta fórmula são os pertencentes a tabela CUSTOMER (tanto os armazenados como fórmulas) e sua tabela estendida.

Page 103: 93909254 GENEXUS Heuristica Apostila Teorica

103

ProductPrice*InvoiceDetailQuantity if InvoiceDetailQuantity<=100;ProductPrice*InvoiceDetailQuantity*0.9 otherwise;

FórmulasClassificação

• Exemplo II de Fórmula Horizontal (Global) :

{ InvoiceId*CustomerId

CustomerName

InvoiceDate

Detail{

InvoiceDetailId*

ProductId

ProductDescription

ProductPrice

InvoiceDetailQuantity

InvoiceDetailAmount }

}

Invoice

Neste exemplo o atributo InvoiceDetailAmount foi definido como fórmula global também. Isto é, utilizando o editor de fórmulas, foi associado um cálculo a este atributo e o mesmo passará a ser um atributo virtual.

A tabela associada ao atributo InvoiceDetailAmount será INVOICEDETAIL, caso dito atributo for armazenado novamente, será criado em dita tabela física.

Como podemos observar a fórmula definida cai na classificação de horizontal, já que consiste em 2 expressões aritméticas condicionais. Os atributos envolvidos na definição da fórmula pertencem a tabela INVOICEDETAIL ou a sua tabela estendida.

Page 104: 93909254 GENEXUS Heuristica Apostila Teorica

104

{ InvoiceId*CustomerId

CustomerName

InvoiceDate

InvoiceDetail � Count(InvoiceDetailQuantity)InvoiceAmount � Sum(InvoiceDetailAmount)Detail{

InvoiceDetailId*

ProductId

ProductDescription

ProductPrice

InvoiceDetailQuantity

InvoiceDetailAmount}

}

Invoice

FórmulasClassificação

• Exemplos de Fórmulas Aggregate (Globais) :

Em ambos os cálculos somente intervém os registros que cumprirem:

INVOICEDETAIL.InvoiceId = INVOICE.InvoiceId

No exemplo os atributos InvoiceDetail e InvoiceAmount foram definidos como fórmulas globais, já que utilizando o editor de fórmulas foi definido uma fórmula para cada um destes atributos (os passando a ser atributos virtuais).

Visto que as fórmulas definidas são Count e Sum respectivamente, em ambos casos se trata de fórmulas Aggregate.

A tabela associada a ambos atributos fórmula é INVOICE, já que caso estes atributos estivesses armazenados, seriam criados em dita tabela física.

As fórmulas Aggregate não possuem somente uma tabela base associada (como todas as fórmulas), mas também envolvem uma tabela a ser navegada.

A tabela a ser navegada numa fórmula Aggregate, é a tabela que será navegada para realizar o cálculo. GeneXus inferi qual a tabela a ser navegada por uma fórmula Aggregate, pelos atributos envolvidos na definição da fórmula. Em nosso exemplo, a tabela a ser navegada em ambas fórmulas Aggregate éINVOICEDETAIL, já que tanto na definição de Sum como Count, temos referenciado a um único atributoassociado a INVOICEDETAIL.

Quando definirmos uma fórmula Aggregate, já temos conhecimento de qual tabela pretendemos navegar para efetuar o cálculo. Os atributos que poderemos referenciar na definição de uma fórmula Aggregate deverão pertencer a tabela a ser navegada e sua tabela estendida + a tabela associada ao atributo que está sendo definido como fórmula e sua tabela estendida. De envolver numa fórmula Aggregate atributos que não pertençam a este contexto mencionado, um error será mostrado na listagem de navegação correspondente.

Por último, havendo atributos em comum (com o mesmo nome) nas tabelas envolvidas na definição de uma fórmula, GeneXus aplicará essa relação (isto é, um filtro automático por igualdade pelos atributos com o mesmo nome). Isto é o que acontece neste 2 exemplos, que GeneXus conta e soma as linhas relacionadas a seus cabeçalhos (ao somar e contar, aplica automaticamente o filtro INVOICEDETAIL.InvoiceId = INVOICE.InvoiceId ).

Page 105: 93909254 GENEXUS Heuristica Apostila Teorica

105

Sintaxe completa de Sum, Count, Average:

Sum | Count | Average(Expressão, [Condição Explícita, Valor por Default]) [if Condição Disparo];

Nos 2 exemplos de fórmulas Sum e Count que vimos, somente definimos o parâmetro obrigatório, a expressão a ser somada o contada (que num caso consistiu num atributo armazenado e no outro caso num atributo fórmula). Também dita expressão poderia envolver constantes e/ou funções.

Vimos que GeneXus determina condições de filtro implícitas ao realizar ao soma, conta ou média/ Também poderíamos ter definido condições de filtro explícitas e no caso de fazê-las, GeneXus levará ambas em consideração: implícitas + explícitas.

De forma opcional é possível definir um valor por default a ser retornado quando não são encontrados registros para contar, somar, ou média.

Da mesma forma que todas as fórmulas, estas também permitem incluir condição de disparo.

Por último, vale mencionar uma exceção e é em particular nas fórmulas Count, o primeiro parâmetro deve corresponder a um atributo e não a uma expressão. Pode referenciar qualquer atributo da tabela na qual se quer contar registros (que cumpram com condições explícitas e/ou implícitas).

Page 106: 93909254 GENEXUS Heuristica Apostila Teorica

106

{ProductId*ProductDescription

PriceList{ProductPriceListDate*ProductPriceListPrice

}}

Product

FórmulasClassificação

• Exemplos de Fórmulas Aggregate (Globais) :

{InvoiceId*CustomerId

CustomerName

InvoiceDate

InvoiceDetail � Count(InvoiceDetailQuantity)InvoiceAmount � Sum(InvoiceDetailAmount)Detail{

InvoiceDetailId*

ProductId

ProductDescriptionInvoiceDetailQuantity

InvoiceDetailProductPriceInvoiceDetailAmount

}}

Invoice

InvoiceDetailProductPrice*InvoiceDetailQuantity

Max(ProductPriceListDate, ProductPriceListDate<=InvoiceDate, 0, ProductPriceListPrice)

Modificamos o desenho das transações para que ao invés de representar que cada produto possui um preço único, representamos que cada produto tem uma lista de preços de acordo com uma data de alteração dos mesmos.

Ao efetuar esta mudança, o atributo ProductPriceListPrice não poderá estar presente no segundo nível da transação Invoice. Por que? Porque o novo desenho estará representando que um produto não vai ter um preço único, mas sim muitos: um para cada data da alteração do preço do mesmo. Portanto um produto numa linha de uma fatura, teremos que “buscar” o preço vigente do mesmo, considerando a data da fatura.

Lembre que os atributos que podem ser inferidos em determinado nível de uma transação, são os que pertencem a tabela estendida da tabela base associada ao nível em questão. Neste exemplo, a tabela estendida da tabela INVOICEDETAIL, não inclui a tabela PRODUCTPRICELIST (naquela que o atributo esteja ProductPriceListPrice):

portanto no nível Detail da transação Invoice (associado a tabela INVOICEDETAIL) não é possível inferir o atributo ProductPriceListPrice (armazenado na tabela PRODUCTPRICELIST).

Page 107: 93909254 GENEXUS Heuristica Apostila Teorica

107

O que ocorre se deixarmos o atributo ProductPriceListPrice no nível Detail transação Invoice? Como não pode ser inferido, então GeneXus não terá outra opção que armazená-lo na tabela INVOICEDETAIL e este atributo secundário já estará em outra tabela (PRODUCTPRICELIST). Como resultado é um modelo de dados não normalizado, e mostrará o error ao querer reorganizar a base de dados.

E como fazemos para mostrar em cada linha da factura, o preço vigente do produto da mesma? De todos os preços correspondentes ao produto de una linha, qual queremos recuperar? Evidentemente, de todos os preços que tenham data menor ou igual a data da fatura, queremos aquele que tenha data maior.

Procedemos então a criar no nível Detail da transação Invoice, um novo atributo de nome InvoiceDetailProductPrice, ao qual o definiremos como fórmula global e portanto será um atributo virtual.

A dito atributo vamos associar a fórmula Max:

GeneXus infere a tabela a ser navegada pelo último parâmetro da fórmula (o atributo de retorno).

Como já se foi explicado, os atributos que poderemos referenciar na definição de uma fórmula Aggregate deverão pertencer a tabela a ser navegada e sua tabela estendida + a tabela associada ao atributo definido como fórmula e sua tabela estendida. Envolvendo atributos que não pertençam neste contexto mencionado, um error é mostrado na listagem de navegaçã correspondente.

GeneXus considera o momento de efetuar a busca a condição explícita de filtro + as condições implícitas detectadas.

A fórmula Min é totalmente análoga a Max, com uma única diferença de que ao encontrar um conjunto de registros que cumpram com as condições, será selecionado aquele registro que tenha valor mínimopara o atributo indicado no primeiro parâmetro e retorne o valor de retorno indicado no último parâmetro.

A fórmula Find por sua vez, também permite buscar um registro que cumpra com certas condições, contudo se ter mais de 1 registro que cumpra com elas, a fórmula devolverá o atributo de retorno correspondente ao primeiro registro encontrado (sem maximizar nem minimizar um valor no conjunto de registros que cumpram com as condições). A sintaxe Find é:

Find (Expressão de retorno, [Condição explícita], [Valor por default) [if Condição de disparo]

Observar que a expressão de retorno neste caso se escreve no primeiro parâmetro da fórmula.

Max(ProductPriceListDate, ProductPriceListDate<= InvoiceDate, 0, ProductPriceListPrice)

Atributo a maximixar entre os registros que cumpram as condições

Para o registro encontrado, se retorna este atributo

Valor de retorno se não encontrar nenhum registro que cumpra con las condições

Condições que devem cumprir os registros para ser considerados

Page 108: 93909254 GENEXUS Heuristica Apostila Teorica

108

Sum(InvoiceAmount) / Count(InvoiceAmount)

FórmulasClassificação

• Exemplo de Fórmula Composta (Global):

{ CustomerId*CustomerNameCustomerTotalPurchasesCustomerTotalPaymentsCustomerBalanceCustomerAverage

}

Customer

Page 109: 93909254 GENEXUS Heuristica Apostila Teorica

109

Comunicaçãoentre objetos

Page 110: 93909254 GENEXUS Heuristica Apostila Teorica

110

Comunicação entre objetos

Procedimento

Procedimento PDF

TransaçãoWeb Panel

Data Provider

Os objetos GeneXus podem comunicar-se entre eles ou com outros programas externos.

Um objeto GeneXus pode chamar ou ser chamado por qualquer outro objeto, trocando informações através de parâmetros.

Veremos em seguida como chamar desde um objeto a outro, e como especificar os parâmetros (no objeto chamador e no chamado) para a troca da informação.

O esquema apresentado acima ilustra as possíveis interações entre objetos GeneXus para uma aplicação Web. Observe que a flecha simples entre Web Panel e Procedimento PDF (assim como entre Transação e Procedimento PDF) indica que uma web panel poderáchamar um Procedimento PDF mas um Procedimento PDF não poderá chamar uma web panel (ou transação Web).

Page 111: 93909254 GENEXUS Heuristica Apostila Teorica

111

2 possibilidades:

1)

2)

Comunicação entre objetos

PgmName.Call(par1 , …, parN)

att|&var = PgmName.Udp(par1, …, parN)

Parm(par1 , …, parN);/*Declaração de parâmetros

no objeto chamado*/

Parm(par1, …, parN , parsaída);

/* Chamada a PgmName*/

/*Declaração de parâmetrosno objeto chamado*/

/*Chamada a PgmName*/

Pode omitir-se

CALL - Permite chamar a um objeto GeneXus ou a um programa externo, podendo passar parâmetros ou não.

UDP (User Defined Procedure)– Permite chamar a um objeto GeneXus ou programa externo tanto passando parâmetros ou não, e com a particularidade de que o programa chamado retornará necessariamente ao menos um valor ao programa que chamou. Em ambientes Web, um objeto com interface uma vez chamado não devolve o controle ao chamador, porque a UDP é utiliza unicamente para chamar Procedimentos e Data Providers (devido que estes cumprem com a condição de executar e devolver o controle ao chamador).

Uma chamada (seja com CALL ou UDP) pode ser utilizado em distintas partes do objeto chamador, dependendo se o mesmo é uma transação, wep panel, procedimento, etc.

A UDP pode utilizar-se também na definição de um atributo formula. Quer dizer que se define que certo atributo é uma formula e que a definição da mesma consiste no chamada a um procedimento utilizando UDP.

Quando na sintaxe da chamada se escreve o nome do objeto chamado e nenhum método de chamada, se assume que se está chamando com udp, e pode ser omitida e escrever diretamente:

att|&var = PgmName( par1, ..., parN)

PARM – Quando um objeto é chamado desde outro com parâmetros, deve ter declarada a lista de parâmetros que recebe. Esta declaração se realiza mediante a regra: PARM.

A continuação daremos mais detalhes sobre o uso de CALL, UDP e PARM.

Page 112: 93909254 GENEXUS Heuristica Apostila Teorica

112

2 possibilidades – Exemplos:

1) A partir da transação Invoice chamamos um procedimento PDF para imprimir a fatura:

2) Ex:

ListInvoice.Call(InvoiceId)

&discount = GetDiscount.udp(ProductId,CustomerId)

Parm(InvoiceId)

Parm(ProductId,CustomerId , &disc);

Comunicação entre objetos

E nas regras do procedimento ListInvoice:

Na proc GetDiscount �

Aqui mostramos um exemplo do uso do CALL para realizar uma chamada e outro exemplo do uso do UDP.

Dependendo de qual objeto for o chamador, estas chamadas poderão escrever-se em uma seção ou outra do mesmo, mas independentemente disso, aqui mostraremos que CALL permite chamar um objeto com estilo de chamada a um programa, enquanto que UDP uma chamada a um objeto com estilo de chamada em uma função.

No primeiro exemplo esta se utilizando CALL para chamar um procedimento pdf (objeto ListInvoice) passando um parâmetro (InvoiceId). No procedimento chamado se declarou o parâmetro que recebe (em sua seção de regras, mediante a regra parm).

No segundo exemplo é utilizado UDP para chamar um procedimento (objeto GetDiscount) passando dois parâmetros (ProductId, CustomerId). Agora observemos na sintaxe da chamada ao procedimento, que o mesmo retornará um valor (na variável &disc). Por este motivo no procedimento solicitado são declarados três parâmetros utilizando a regra parm: os dois parâmetros recebidos + o parâmetro de retorno no último lugar.

Podemos ver então que quando se utiliza CALL para chamar um objeto enviando-lhe N-parâmetros, se devem declarar os N parâmetros (posicionais e do mesmo tipo de dados que os enviados) no objeto solicitado mediante a regra parm.

Por outro lado quando se utiliza UDP para chamar um objeto enviando N parâmetros (exceto que seja o caso particular de um Data Provider, caso que veremos mais adiante):• na regra parm do objeto chamado se devem declarar N + 1• o último parâmetro declarado na regra parm do objeto chamado corresponde ao que se encontra no começo de tudo na chamada, é dizer, ao que recebe o valor retornado. • em algum lugar do objeto chamado deverá ser atribuído valor ao parâmetro de retorno.

Page 113: 93909254 GENEXUS Heuristica Apostila Teorica

113

Declarar o que na regra parm: variável ou atributo?

• Variável: Pode ser utilizada livremente, na lógica do objeto chamado:

• como condição de filtro por =, >, >=, <, <=, LIKE, etc.

• para alguma operação aritmética.

• como flag (bandeira).

• etc.

• Atributo: Automaticamente o mesmo atuará como filtro por igualdade no objeto, não sendo possível modificar o valor recebido.

Ao definir uma Chamada a um objeto (seja utilizando CALL ou UDP), se tivermos que enviar dados por parâmetro ao objeto chamado, precisamos determinar se enviaremos atributos e/ou variáveis: se um dado a ser enviado por parâmetro, se encontra no objeto que o chamou, em um atributo, terá que enviar o mesmo; e se estiver numa variável, teráque enviar a variável.

Todavia, ao declarar a lista de parâmetros no objeto chamado, o programador GeneXus deverá decidir para cada parâmetro, se o declara como um atributo ou uma variável, independentemente de como tenha sido enviado.

Qual é a diferença entre declarar o parâmetro como variável ou como atributo na regra parm do objeto chamado? Se for declarar como uma variável, poderá utilizar livremente a mesma lógica do objeto chamado: pode utilizá-la como condição de filtro por igualdade, por maior, maior ou igual, menor, menor ou igual, LIKE, etc.; poderá utilizar para alguma operação aritmética, como bandeira (flag), ou para o que se queira. Se for declarar um atributo, automaticamente o mesmo atuará como filtro por igualdade no objeto, não sendo possível modificar o valor recebido.

Quando cheguemos à etapa do curso na qual podemos chamar a procedimentos pdf para listagem, passando parâmetros, assim como a outros objetos, poderemos terminar de compreender melhor este tema.

Page 114: 93909254 GENEXUS Heuristica Apostila Teorica

114

Definição de tipo de passagem de parâmetros (in, out, inout)

• Para cada parâmetro declarado na regra parm, é possível definir que o mesmo seja:

− de entrada (in)

− de saída (out)

− de entrada-saída (inout)

• Exemplo: parm( out:&par1, in:&par2, &par3, inout:&par4);

• Vantagens:• Melhor especificação da semântica das interfaces.

• Independência da linguagem de geração.

• Otimizar a passagem de parâmetros das aplicações de acordo com a arquitetura implementada (vantagem que contrasta com a anterior).

Como pode-se perceber claramente na sintaxe do exemplo o primeiro parâmetro definido é de saída, o segundo parâmetro é de entrada, e o quarto parâmetro é de entrada-saída. Quando não for especificado, como é o caso do terceiro parâmetro do exemplo, dependerá do seguinte:

• se o objeto foi chamado com CALL, o parâmetro, será de entrada-saída.• se o objeto foi chamado com UDP, e se trata do último parâmetro, será de saída; e se for outro parâmetro diferente do último, dependerá da linguagem de operação.

Declarar explicitamente como se quer que cada parâmetro opere, possui as seguintes vantagens:1. Melhor especificação da semântica das interfaces; ou seja, o GeneXus e o programador quando trabalham com um objeto, fica claro:

- se o mesmo chegar com valor e depois da execução do objeto chamado, édevolvido ao objeto que o chamou o valor que tenha ficado (inout).

- se o mesmo chegar com valor e depois da execução do objeto chamado, não devolve ao objeto que o chamou o valor que tenha ficado (in).

- se o mesmo não chegar com valor e depois da execução do objeto que o chamado, se devolve ao objeto que o chamou o valor que tenha ficado (out).

2. Independência da linguagem de geração; isto é, se define explicitamente como deseja que cada parâmetro opere, ao gerar as aplicações utilizando diferentes linguagens de geração não muda o comportamento dos parâmetros baseados ao comportamento por default da linguagem de geração correspondente.

3. Otimizar a passagem de parâmetros de acordo com a arquitetura gerada (sendo uma vantagem que contrasta com a anterior); isto se refere que para a maioria das linguagens é mais eficiente passar os parâmetros por referência (inout) que por valor (in / out); mas em Java, por exemplo, os parâmetros somente podem ser passados por valor, para poder obter esta funcionalidade de passá-los por referência é necessário que exista conversões de parâmetros, que pode redundar em umoverhead importante; por outro lado, quando se trata de aplicações distribuídas (por exemplo Java com RMI ou HTTP), a utilização de parâmetros de tipo out têm a vantagem de que não é necessário enviar parâmetro na chamada, diferente de definir os parâmetros inout (tem que passar todos parâmetros); isto tem como conseqüência que serão enviados mais bytes do que os necessários, o que é inconveniente especialmente nos casos como Internet.

Page 115: 93909254 GENEXUS Heuristica Apostila Teorica

115

Mais possibilidades para definir chamadas ���� Função Link

1)

2)

Comunicação entre objetosWeb

control.Link = PgmName.Link([,par1 …, parN])

Ex: imagem.Link = Link(‘http://www.artech.com.uy’)

Ex: imagem.Link = Customer.Link()

control.Link = Link(URL)

Os parâmetros são opcionais e no caso de existirem, são declarados com a regra parm

A função Link se associa à propriedade link de um controle dentro de qualquer evento de uma transação ou web panel, tendo como resultado que ao fazer click sobre dito controle se realiza a chamada ao objeto URL referenciada no Link.

PgmName (o objeto chamado) poderá ser uma web panel, transação, ou procedimento PDF1.

____________________________________________________________________

1 também um procedimento HTTP, mas não aprofundaremos sobre este conceito neste curso

Page 116: 93909254 GENEXUS Heuristica Apostila Teorica

116

Mais possibilidades para definir chamadas ���� Comando Link

1)

2)

Comunicação entre objetosWeb

Ex: Customer.Link(CustomerId)

PgmName.Link([,par1 …, parN])

Ex: Link(‘http://www.google.com’)

Link(URL)

O comando Link pode ser utilizado dentro de qualquer evento de uma transação ou web panel¹

Quando se execute o evento, ao chegar a sentença com o comando Link, se redirecionaráem forma automática à URL especificada.

No caso de utilizar-se o comando Link como no exemplo 1, chamando um PgmName (sendo PgmName uma web panel, transação ou procedimento PDF), será equivalente àutilização do Call. Opcionalmente se poderá passar parâmetros ao objeto chamado, devendo declarar-se os mesmos no objeto chamado, com a regra parm.

___________________________________________________________________

1 também um procedimento HTTP, mas não aprofundaremos sobre este conceito neste curso

Page 117: 93909254 GENEXUS Heuristica Apostila Teorica

Ordem de execução de regras e fórmulas

Page 118: 93909254 GENEXUS Heuristica Apostila Teorica

“Category”CategoryId*CategoryDiscount

“Customer”CustomerId*CustomerNameCategoryIdCustomerTotalPurchases

“Shipping”ShippingDate*ShippingCharge

Add( InvoiceTotal, CustomerTotalPurchases);Error( ‘Insufficient Stock’ ) if ProductStock<0;Subtract( InvoiceDetailQuantity, ProductStock);

InvoiceId*InvoiceDateCustomerIdCustomerTotalPurchasesCategoryDiscountInvoiceDiscount = InvoiceSubTotal *CategoryDiscountInvoiceShippingCharge = Max( ShippingDate, ShippingDate

<=InvoiceDate,,ShippingCharge)InvoiceSubTotal = SUM( InvoiceDetailAmount )InvoiceTotal = InvoiceSubTotal – InvoiceDiscount

+ InvoiceShippingCharge{ProductId*ProductPriceProductStockInvoiceDetailQuantityInvoiceDetailAmount} = InvoiceDetailQuantity *

ProductPrice

“Product”ProductId*ProductPriceProducStock

Transação "Invoice"

Regras:

Ordem de execução deregras e fórmulas

A forma de programar o comportamento das transações é definindo regras, escritas de forma declarativa. Quando temos cálculos para efetuar, podemos optar pela alternativa de definir atributos fórmulas.

Em nenhum momento, o programador GeneXus especifica a seqüência de execução das regras e fórmulas definidas em uma transação. Quando for gerar, o GeneXus determina as dependências existentes entre as regras e fórmulas definidas.

Vamos supor que estamos definindo uma aplicação para uma empresa que vende determinados produtos, e que conta com um serviço de entrega a domicílio que leva a mercadoria a seus clientes. E definimos entre outras, as seguintes 5 transações:

“Customer” (para registrar os clientes da empresa)“Category” (as que pertencem cada cliente)“Shipping” (envios: guarda um histórico de custos de envio)“Invoice” (faturas emitidas aos clientes)“Product” (produtos que são vendidos pela empresa)

Ressaltamos a estrutura da transação “Invoice”, com seus atributos fórmulas e suas regras declaradas.

Em que ordens serão disparadas as regras e fórmulas da transação “Invoice”?

Page 119: 93909254 GENEXUS Heuristica Apostila Teorica

R. Add(InvoiceTotal, CustomerTotalPurchases);F. InvoiceTotal = InvoiceSubTotal - InvoiceDiscount +

InvoiceShippingChargeF. InvoiceDiscount = InvoiceSubTotal*CategoryDiscountF. InvoiceShippingCharge = MAX( ShippingDate, ShippingDate <=

InvoiceDate,,ShippingCharge)F. InvoiceSubTotal = SUM( InvoiceDetailAmount )F. InvoiceDetailAmount = InvoiceDetailQuantity *ProductPriceR. Subtract(InvoiceDetailQuantity, ProductStock) ;R. Error( ‘Insuffcient Stock’) if ProductStock < 0 ;

Árvore de avaliação

error (‘Insufficient Stock ’)

ProductStock

InvoiceDetailQuantity

InvoiceDetailAmount

InvoiceTotal

InvoiceSubTotal

InvoiceDiscount

ProductPrice

CategoryDiscount

CustomerTotalPurchases

InvoiceShippingCharge

InvoiceDateShippingDate

ShippingCharge

No momento de gerar o programa associado na transação “Invoice”, o GeneXus determinará as dependências existentes entre as regras e fórmulas definidas; e construirá logicamente uma árvore de dependências (ou árvore de avaliação) que determinará a seqüência de avaliação.

Podemos imaginar que a árvore é executada de baixo para cima, cada vez que alteramos algum valor de um atributo, se executam todas as regras e fórmulas que dependem desse atributo (e que na árvore se encontram para cima).

Por exemplo, alterando a quantidade de uma linha de uma fatura (InvoiceDetailQuantity), como este atributo interfere na fórmula que calcula o valor da linha (InvoiceDetailAmount), esta fórmula serádisparada novamente. Para alterar o valor de uma linha, a fórmula é disparada novamente correspondendo ao subtotal da fatura (InvoiceSubTotal) e como conseqüência, também deverá ser recalculada a fórmula correspondente ao desconto (InvoiceDiscount), já que depende do subtotal. Deverá ser disparada novamente a fórmula correspondente ao total da fatura (InvoiceTotal) já que depende tanto do valor de InvoiceSubTotal como do valor de InvoiceDiscount. Por último, por alterar o total, também será disparada a regra Add(InvoiceTotal, CustomerTotalPurchases).

Além de serem disparadas todas as fórmulas e regras envolvidas na parte direita da Árvore desde o atributo InvoiceDetailQuantity, também são disparadas as fórmulas e regras envolvidas na parte esquerda. Ou seja, ao alterar o valor do atributo InvoiceDetailQuantity, será disparada novamente também a regra Subtract(InvoiceDetailQuantity, ProductStock); e em conseqüência, por modificar esta regra o valor do atributo ProductStock verifica a necessidade de disparar a regra Error(‘Insufficient Stock’’) if ProductStock < 0;

Concluindo, as regras e fórmulas que se definem numa transação estão inter-relacionadas e GeneXus determina as dependências entre elas assim como sua ordem de avaliação.

Observemos as 2 últimas regras definidas:

Subtract(InvoiceDetailQuantity, ProductStock);Error(‘Insufficient Stock’) if ProductStock < 0;

Page 120: 93909254 GENEXUS Heuristica Apostila Teorica

Estas regras estão inter-relacionadas porque envolvem o atributo ProductStock. Agora, enquanto que a segunda somente consulta seu valor, a primeira o atualiza. Então, a regra que atualiza o atributo será a que vai disparar o primeiro, e em seguida dispara a que o consulta.

Toda regra que atualize o valor de um atributo, será disparada antes que uma regra que o consulte (isto pode ser observado claramente na árvore). Por este motivo é que a regra Error consulta se o atributo ProductStock ficou com valor negativo; porque como sabemos que a subtração será realizada primeiro,.

Na programação clássica primeiro consulta-se o estoque, a subtração é realizada quando ele for suficiente. Por isso quem está aprendendo GeneXus pode intuitivamente escrever a regra: Error(Insufficient Stock’) ifInvoiceDetailQuantity > ProductStock. Esta sintaxe é correta, não é correta sua lógica, já que como temos explicado, na árvore de avaliação determinada pelo GeneXus primeiro é disparada a regra Subtract e depois a regra Error; portanto temos que definir que se dispare a mensagem de error se o estoque ficou o stock com valor negativo, já que será executado a subtração no momento de consultar o valor de ProductStock.

Assim que a regra deve definir é:

Error(‘Insufficient Stock’) if ProductStock < 0;

E não:

Error('Insufficient Stock') if InvoiceDetailQuantity > ProductStock;

Quando se dispara uma regra Error, se detêm qualquer atualização da base de dados e desarma a árvore de avaliação, ficando no estado anterior ao se produzir o erro. Seguindo o exemplo que estamos vendo, se ao disparar a regra Subtract o stock que ficará negativo, se dispararia a regra Error. Como conseqüência ao se disparar a regra Error, o Subtract que foi executado é desfeito, assim como todas as demais regras e fórmulas que tenham executado (recálculo dos atributos InvoiceDetailAmount, InvoiceSubTotal, ...., CustomerTotalPurchases).

Page 121: 93909254 GENEXUS Heuristica Apostila Teorica

Alterações da ordem de disparodas regras

SupplierId*InvoiceId*...InvoiceEntTotal Entered Total{ ProductId*InvoiceDetailQuantityInvoiceDetailPriceInvoiceDetailAmount = InvoiceDetailPrice * InvoiceDetailQuantity}

...InvoiceCalcTotal = SUM(InvoiceDetailAmount) Calculated Total

Error

Total Calculado

Total Ingressado

InvoiceDetailAmount

Error(‘The calculated total doesn’t match with the entered total') if (InvoiceEntTotal<>InvoiceCalcTotal) On AfterLevel Level ProductId;

Na maioria dos casos a ordem de execução das regras definida pelo GeneXus a partir de nossas especificações é o desejado. Porém em alguns casos podemos querer alterar o momento de disparo de uma Regra.

Exemplo:Definimos uma transação para registrar as faturas que recebemos de nossos fornecedores.O identificador do primeiro nível é composto pelo código do fornecedor e o número de fatura, já que o número de fatura não nos serve como identificador único, porque fornecedores distintos podem repetir o mesmo número de fatura.Para cada fatura de um fornecedor que inserimos, nos interessa controlar que o total que venha escrito na fatura (e que será digitado no atributo InvoiceEntTotal) seja correto. Para fazer este controle, definimos o atributo InvoiceCalcTotal como fórmula verticalSUM(InvoiceDetailAmount), e agregamos uma regra Error que será disparada se não coincidir os valores dos atributos InvoiceEntTotal e InvoiceCalcTotal:

Error(‘The calculated total doesn’t match with the entered total') if InvoiceCalcTotal <> InvoiceEntTotal;Se construirmos a árvore de avaliação correspondente as fórmulas e regra que definimos nesta transação:

Page 122: 93909254 GENEXUS Heuristica Apostila Teorica

vemos que as dependências indicam que cada vez que são inseridos, modificados ou eliminados valores dos atributos InvoiceDetailAmount e InvoiceDetailQuantity nas linhas, recalcula-se o valor do atributo InvoiceDetailAmount correspondente; em conseqüência, recalculamos o valor do atributo fórmula InvoiceCalcTotal que temos definido para ter o total calculado da fatura; e como o atributo fórmula InvoiceCalcTotal está envolvido na condição de disparo da regra Error, cumpre a dita condição de disparo e dispara a regra Error(‘The calculated total doesn’t match with the entered total’) if InvoiceCalcTotal <> InvoiceEntTotal;

Agora, prestamos atenção a condição de disparo InvoiceCalcTotal<>InvoiceEntTotal vai ser cumprida repetidamente na medida em que o operador vai inserindo as linhas, porque para cada linha que é inserida, calcula-se o valor do atributo fórmula InvoiceDetailAmount da linha, e como consequência é recalculado o valor do atributo fórmula InvoiceCalcTotal. Mas o valor calculado do atributo InvoiceCalcTotal não coincidirá com o valor inserido no atributo InvoiceEntTotal até que não tenham ingressado todas as linhas da fatura; então, dispara-se a regra Error(‘The calculated total doesn’t match with the entered total’) if InvoiceCalcTotal <> InvoiceEntTotal;.

Concluímos então que neste caso, não nos serve o determinado na árvore de avaliação, já que não queremos que seja analisada a condição de disparo da regra Error cada vez que o operador insira, altere ou elimine as linhas, e sim necessitamos que seja analisada quando o usuário tenha terminado trabalhar com todas as linhas da fatura.

GeneXus oferece eventos ou momentos de disparo nas transações, que ocorrem antes ou depois de determinada ação, como a gravação do cabeçalho, ou de uma linha. As regras das transações podem serem condicionadas de tal maneira que sejam disparadas no momento específico que ocorre algum desses eventos de disparo.Seguindo o exemplo visto, existe um evento de disparo que ocorre assim que entramos num nível e saímos do mesmo. A sintaxe deste evento de disparo é: AfterLevel Level Atributo, devendo Atributo um atributo pertencente ao nível interagido e que se abandona.

De modo que a regra Error de nosso exemplo, agregaríamos este evento de disparo, e ficaria definida da seguinte forma:

Error(‘The calculated total doesn’t match with the entered total’) if InvoiceCalcTotal<>InvoiceEntTotal On AfterLevel ProductId;

Agregando este evento de disparo a regra controlamos o que se deseja no momento adequado.

Além deste evento de disparo, existem outros que veremos em seguida.

Page 123: 93909254 GENEXUS Heuristica Apostila Teorica

• BeforeValidate

• AfterValidate

• BeforeInsert, BeforeUpdate, BeforeDelete

• AfterInsert, AfterUpdate, AfterDelete

• AfterLevel

• BeforeComplete

• AfterComplete

Eventos de disparo

� A maioria das regras nas transações permitem agregar um evento ou momento de disparo.

� Ao agregar um evento ou momento de disparo a uma regra, estaremos especificando que a regra deve ser executada nesse determinado momento.

� Eventos de disparo:

No momento da confirmação da transação, ocorre uma série de ações que é necessário para poder programar corretamente o comportamento das regras.Para uma transação de dois níveis, poderíamos enumerá-las como segue:

• validação dos dados do cabeçalho• gravação física do cabeçalho (seja inserção, modificação ou eliminação)• validação dos dados da primeira linha• gravação física dos dados da primeira linha• validação dos dados da segunda linha• gravação física dos dados da segunda linha• …• validação dos dados da n-ésima linha• gravação física dos dados da n-ésima linha• commit

A ação de “validação dos dados do cabeçalho” ocorre após todos serem validados e cada um dos campos informados no cabeçalho. Observar que neste ponto já foi disparado todas as regras que correspondiam aos atributos do cabeçalho e que não tinham evento de disparo associado (exemplo: Default(InvoiceDate, &today)). Imediatamente depois será gravado o registro correspondente ao cabeçalho.

Análogo é o caso das linhas: “a validação dos dados de uma linha” ocorre após todos serem validados e cada um dos dados da linha, e também após terem sido disparadas todas as regras correspondentes segundo a árvore de avaliação (exemplo: subtract( InvoiceDetailQuantity, ProductStock)). Imediatamente depois desta ação de validação, será gravado fisicamente o registro correspondente linha.

Cada transação, ao terminar de trabalhar com um cabeçalho e suas linhas, realiza um commit (é automático). Serácolocado no código gerado por GeneXus, exceto se o analista especifique o contrário, como veremos mais adiante. Isto é, se os dados de duas faturas distintas forem ingressados utilizando a transação “Invoice”, após serem ingressados os dados da primeira, os registros serão comitados, e depois será ingressado o segundo, ao qual seus registros serão comitados.

Os eventos de disparo de regras permitem condicionar o disparo de uma regra da transação para que se execute antes ou depois de alguma das ações que acabamos de enumerar. Veremos quando ocorre cada evento de disparo.

Page 124: 93909254 GENEXUS Heuristica Apostila Teorica

Evento de disparo: BeforeValidate

Este evento de disparo ocorre um pouco antes da informação da instancia que se trabalhe (cabeçalho ou linha) seja validada (ou confirmada). Isto é, ocorrerá antes da ação de “validação do cabeçalho” ou “validação da linha”, correspondente. Observar que aqui também haverão disparadas todas as regras segundo a árvore de avaliação que não estejam condicionadas com nenhum evBeforeento de disparo.

Eventos de disparo: AfterValidate, BeforeInsert, BeforeUpdate, BeforeDelete

O evento de disparo AfterValidate permite definir que uma regra seja executada imediatamente antes de que gravemos fisicamente cada instancia do nível ao qual está associada a regra, na tabela física correspondente e depois de ter validado os dados desta instancia.

Em outras palavras, agregando o evento de disparo AfterValidate a uma regra, a mesma executará, para cada instancia do nível ao qual esteja associada a regra, imediatamente antes de que a instancia seja gravada fisicamente (seja quando insere, altere ou elimine) como registro na tabela física associada ao nível.

EXEMPLOS

1.Tem vezes que não contamos com a possibilidade de utilizar a Propriedade Autonumber para numerar de forma automática e correlativa os atributos que são chave primária simples. Tal funcionalidade é prevista pelos administradores de base de dados (DBMSs) e o GeneXus a aproveita e permite usá-la; nos casos em que não trabalhamos com um administrador de base de dados, não temos a possibilidade de selecionar esta facilidade.

Nesses casos que não contamos com a possibilidade de utilizar a Propriedade Autonumber e necessitamos numerar de forma automática e correlativa certos atributos, devemos resolver nós mesmos na programação. Para fazê-lo somente definindo uma transação contendo ao menos dois atributos, um para armazenar um literal e outro para armazenar o último número atribuído automaticamente ao atributo descrito pelo literal1; a transação vai fazer com que seja criada uma tabela, e temos que definir um procedimento que consulte essa tabela, obtenha o último número atribuído para o atributo a ser numerado, some um e devolva o próximo número, além de atualizá-lo na tabela.

Para chamar ao procedimento de numeração automática se deve definir nas transações que o requerem a seguinte regra:

CustomerId = PGetNumber.udp( ‘CUSTOMER’ ) if Insert on AfterValidate;

Neste caso se está querendo serializar o atributo CustomerId da transação “Customer”

Do mesmo modo, se queremos serializar o identificador de faturas, escreveríamos na transação “Invoice” com a seguinte regra:

InvoiceId = PGetNumber.udp( ‘INVOICE’ ) if Insert on AfterValidate;

Desta forma definimos que se efetuam numerações automáticas nas transações unicamente quando se realizem inserções (pela condição de disparo: if Insert) e imediatamente antes do registro ser gravado fisicamente cada instancia a ser inserida (pelo evento de disparo: on AfterValidate) através do primeiro nível da transação (porque nas duas regras de chamadas que foram mostradas, tem somente um atributo envolvido que pertence ao primeiro nível das transações “Customer” e “Invoice” respectivamente).

O motivo pelo qual agregamos o evento de disparo on AfterValidate a estas regras é para chamar o procedimento de numeração automática imediatamente antes de que seja inserido o registro na base de dados e depois da validação, tentando desta forma ter o maior grau de segurança possível ao número atribuído que será utilizado (e não perder números). Caso a regra fosse disparada sem ter condição, e no caso de faltar alguma validação dos dados do cabeçalho. A resposta é simples: um número seria perdido. Ou seja, se o número da fatura anterior for 5 e o usuário quer informar a seguinte fatura, a regra de atribuição com udp chama o procedimento de numeração que seria disparado assim que ingressar na transação com modo insert, porque o primeiro atributo do cabeçalho é utilizado. O procedimento devolveria o número 6, e se ao validar os dados do cabeçalho encontrar algum error que não permita continuar com o processo, abandonar a transação, por exemplo, esse número 6 seria perdido e a próxima fatura, que deveria ter o número 6 não o terá, e sim o número 7.

________________________________________________________________________________________1 Quando vimos a regra serial falamos este tema de numeração de cabeçalho, com a transação "Number” que era a que tinha o literal: NumberCode e o último número atribuído a transação correspondente a esse literal: NumberLast

Page 125: 93909254 GENEXUS Heuristica Apostila Teorica

Existem 3 eventos de disparo que ocorrem no mesmo momento que o AfterValidate, mas já possuem o modo de forma intrínseca. São eles: BeforeInsert, BeforeUpdate e BeforeDelete.É equivalente escrever a regra apresentada como:

InvoiceId = PGetNumber.udp( 'INVOICE' ) on BeforeInsert;

Observar que aqui é redundante condicionar a regra a “If Insert”. Portanto, as seguintes equivalências são válidas:

on BeforeInsert ∼ If Insert on AfterValidateon BeforeUpdate ∼ If Update on AfterValidateon BeforeDelete ∼ If Delete on AfterValidate

Se tivermos um esquema das ações que rodeiam o disparo do evento, ficam claros os dois sinônimos escolhidos para este evento (AfterValidate e BeforeInsert para modo insert)

VALIDAÇÃO DOS DADOSAfterValidate – BeforeInsert – BeforeUpdate – BeforeDeleteGRAVAÇÃO DO REGISTRO (insert, update, delete segundo corresponda)

2) Se definirmos uma regra em que incluímos também o evento de disparo on AfterValidate, ou on BeforeInsert, BeforeDelete, BeforeUdate, mas a diferença dos exemplos recém vistos, é referenciado na regra pelo menos um atributo do segundo nível da transação na qual está definindo a regra, a mesma estará associada ao segundo nível1. Portanto, a regra executará imediatamente antes que seja gravada fisicamente cada instancia correspondente ao segundo nível da transação.

Eventos de disparo: AfterInsert, AfterUpdate, AfterDelete

Assim como existe um evento de disparo que permite definir que determinadas regras sejam executadas imediatamente antes que seja produzida a gravação física de cada instancia de um nível (AfterValidate, BeforeInsert, BeforeUpdate e BeforeDelete), também existem eventos de disparo para definir que certas regras sejam executadas imediatamente depois de que sejam inseridas, modificadas ou eliminadas fisicamente instancias de um nível. Estes eventos são AfterInsert, AfterUpdate e AfterDelete.

O evento de disparo AfterInsert permite definir que uma regra execute imediatamente depois de que seja inserida fisicamente cadainstancia do nível ao qual está associada a regra; o AfterUpdate depois de atualizar fisicamente a instancia, e o AfterDelete depois de eliminar.

EXEMPLOS

Vamos supor que na transação “Customer” queremos chamar um relatório que realize a impressão dos dados de cada cliente com o qual trabalhamos por meio da transação.

Em que momento devemos realizar as chamadas ao relatório a partir da transação?

Caso 1: RPrintCustomer.call( CustomerId ) on AfterValidate;

Não é adequado agregar-lhe este evento de disparo a regra de chamadas ao relatório, porque o mesmo seria chamado imediatamente antes da gravação física de cada cliente. Em conseqüência, o relatório não encontraria o cliente com seus dados na tabela CUSTOMER (caso estivesse inserindo um cliente por meio da transação), ou o encontraria com seus dados desatualizados (caso estivesse modificando um cliente por meio da transação). Se na alteração estivesse eliminando um cliente por meio da transação, o relatório encontraria os dados do cliente na tabela CUSTOMER e os listaria justamente antes da atualização física (eliminação).

Caso desejarmos emitir uma lista com os dados de cada cliente que forem eliminados, seria adequado definir a seguinte regra:

RPrintCustomer.call( CustomerId ) on BeforeDelete;ou equivalente:RPrintCustomer.call( CustomerId ) if delete on AfterValidate;

________________________________________________________________________________________________

1 Existe outra forma de provocar que uma regra que contem atributos de um nível determinado, se dispare no nível seguinte, por meio de cláusula Level que foi mencionado quando vimos conceitos importantes sobre as regras de transações.

tem

po

Page 126: 93909254 GENEXUS Heuristica Apostila Teorica

para restringir o disparo da regra unicamente quando estamos eliminando um cliente, porque é o único caso em que seria correto utilizar o evento de disparo AfterValidate (já que justamente necessitamos emitir o relatório antes da eliminação).

Caso 2: RPrintCustomer.Call( CustomerId ) on AfterInsert;

O evento de disparo AfterInsert ocorre imediatamente depois de que inserimos fisicamente cada instancia associada a certo nível da transação (neste caso, como o único atributo envolvido na regra é CustomerId, trata-se de uma regra associada ao primeiro e único nível da transação “Customer”).

Como indica claramente pelo seu nome, o evento de disparo AfterInsert somente ocorre ao inserir uma nova instancia (precisamente após ser inserida como registro físico). Utilizando ele quando se agrega o evento de disparo on AfterInsert a uma regra, não é necessário agregar-lhe a condição de disparo if insert.

É correto agregar este evento de disparo a regra de chamadas ao relatório, já que o relatório seria chamado imediatamente depois de que fosse inserido fisicamente cada cliente. Assim que o relatório encontrar o cliente com seus dados na tabela CUSTOMER e os imprime.

O que deve ficar claro é que com esta definição, o relatório é chamado unicamente logo que realizar inserções.

Caso 3: RPrintCustomer.Call( CustomerId ) on AfterUpdate;

O evento de disparo AfterUpdate ocorre imediatamente depois que é atualizada fisicamente cada instancia associada a certo nível da transação (neste caso, como o único atributo envolvido na regra é CustomerId, se trata de uma regra associada ao primeiro e único nível da transação “Customer”).

É adequado agregar neste evento de disparo a regra de chamadas ao relatório, já que o relatório é chamado imediatamente depois que for atualizado fisicamente um cliente. Assim que o relatório encontrar o cliente com seus dados atualizados na tabela CUSTOMER e os imprimir.

O relatório será chamado unicamente após realizar as atualizações.

Caso 4: RPrintCustomer.Call( CustomerId ) on AfterDelete;

O evento de disparo AfterDelete ocorre imediatamente depois da eliminação física de cada instancia associada a certo nível da transação (neste caso, como o único atributo envolvido na regra é CustomerId, se trata de uma regra associada ao primeiro e único nível da transação “Customer”).

Não é adequado agregar este evento de disparo a regra de chamadas ao relatório, porque o relatório é chamado imediatamente depois da eliminação física de cada cliente. Em conseqüência, o relatório não encontra o cliente com seus dados na tabela CUSTOMER.

Caso 5: RPrintCustomer.Call( CustomerId ) on AfterInsert, AfterUpdate;RPrintCustomer.Call( CustomerId ) if delete on AfterValidate;

Para finalizar, estas duas regras são adequadas para chamar um relatório na transação “Customer”, com o objetivo de imprimir os dados de cada cliente com qual trabalhar, abrangendo os três modos de trabalho.

Como podemos observar na primeira regra, é possível incluir vários eventos de disparo separados por vírgula, quando os mesmos aplicam a uma mesma regra.

Isto é, é o mesmo que definir duas regras independentes:

RPrintCustomer.Call( CustomerId ) on AfterInsert;RPrintCustomer.Call( CustomerId ) on AfterUpdate;

que esta regra:

RPrintCustomer.Call( CustomerId ) on AfterInsert, AfterUpdate;

Page 127: 93909254 GENEXUS Heuristica Apostila Teorica

Caso 6: Se definirmos uma regra a qual incluímos o evento de disparo on AfterInsert, mas a diferença dos exemplos vistos recentemente, é referenciada na regra pelo menos um atributo do segundo nível da transação na qual estamos definindo a regra, a mesma estará associada ao segundo nível. Portanto, a regra é executada imediatamente depois de que inserimos fisicamente cada instancia correspondente ao segundo nível da transação.

Analogamente é o caso de disparo de on AfterUpdate e on AfterDelete.

Ampliamos o esquema que havíamos efetuado antes, das ações que rodeiam aos eventos de disparos visto até agora:VALIDAÇÃO DOS DADOSAfterValidate – BeforeInsert – BeforeUpdate – BeforeDeleteGRAVAÇÃO DO REGISTRO (insert, update, delete segundo corresponda)AfterInsert – AfterUpdate – AfterDelete

Este esquema se repete para cada instancia do nível. Por exemplo, pensamos no ingresso das linhas de uma fatura.Este esquema ocorre para cada linha, podemos pensar num loop que se repete até que a última linha seja gravada.

A ação depois da última linha seria gravada é quando sai desse nível (neste caso as linhas da fatura). E depois dessa ação, exceto que tenha outro nível, nesse caso voltaria o esquema anterior, ocorrerá o commit que é a última ação de execução.

Entre a ação de abandonar o nível, e o commit temos um evento (que admite dois nomes distintos) e outro para depois do commit. São o que veremos na continuação mas que já vamos mostrar no esquema:

VALIDAÇÃO DOS DADOS CABEÇALHOAfterValidate – BeforeInsert – BeforeUpdate – BeforeDeleteGRAVAÇÃO DO REGISTRO (insert, update, delete segundo corresponda)AfterInsert – AfterUpdate – AfterDelete

VALIDAÇÃO DOS DADOS LINHAAfterValidate – BeforeInsert – BeforeUpdate – BeforeDeleteGRAVAÇÃO DO REGISTRO (insert, update, delete segundo corresponda)AfterInsert – AfterUpdate – AfterDelete

ABANDONAR NÍVEL 2AfterLevel - BeforeCompleteCOMMITAfterComplete

tem

po

tem

po

loop

Page 128: 93909254 GENEXUS Heuristica Apostila Teorica

Eventos de disparo: AfterLevel, BeforeComplete

O evento de disparo AfterLevel permite definir que uma regra seja executada imediatamente depois de terminar de interagir determinado nível.SINTAXE: regra [if condição de disparo] [on AfterLevel Level atributo];

ONDE: regra: é uma regra das permitidas em transaçõescondição de disparo: é uma expressão booleana que permite envolver atributos, variáveis, constantes e funções, assim como os operadores Or, And, Not. atributo: é um atributo pertencente ao nível para o qual se deseja que depois de ser iterado, se execute a regra.

FUNCIONALIDADE:

Se o atributo que especificamos na continuação do evento de disparo AfterLevel pertencer ao segundo nível da transação, a regra será executada quando terminar de interagir com todas as linhas do segundo nível.

E se o atributo especificado em seguida do evento de disparo AfterLevel pertencer ao primeiro nível, - seguindo o mesmo conceito - a regra será executada quando tenha terminado de interagir com todos os cabeçalhos. Observar que isto ocorre no final de tudo, ou seja, uma vez que tivermos inserido todos os cabeçalhos e suas linhas e fechado a transação (nesse momento terão interagido todos os cabeçalhos). Portanto, se o atributo especificado pertencer ao primeiro nível, à regra será disparada uma vez somente antes do Evento Exit (é um evento que executa uma vez quando fechamos uma transação em tempo de execução, como veremos).

Exemplo: Rever o exemplo apresentado anteriormente, onde tínhamos uma transação para representar as Faturas dos fornecedores, e onde tínhamos que controlar que o total calculado de cada fatura coincida com o total informado. Tínhamos a regra:

Error(‘The calculated total doesn’t match with the entered total ') if InvoiceCalcTotal<>InvoiceEntTotal;

que necessitamos que se dispare depois de todas as linhas da fatura do Fornecedor serem informadas. Portanto, o evento de disparo apropriado será AfterLevel att, onde att pode ser qualquer atributo das linhas.

O evento de nome BeforeComplete, neste caso, coincide com o AfterLevel. Se observarmos o esquema apresentado na página anterior, podemos ver que o tempo que tem entre sair do último nível e a realização do commit é o instante que ocorrem estes eventos. São 02 (dois) nomes para nos referimos ao mesmo.

Cuidado que isto é sempre assim e quando o nível abandonado é o último. Por exemplo uma transação com dois níveis paralelos. Se agregamos ao cliente suas direções de mail e seus números telefônicos (pode ter vários):

CustomerId*CustomerName…{CustomerPhone*…}

{CustomerEMail*…}

O momento em que deverá disparar uma regra condicionada a: On AfterLevel Level CustomerPhone NÃO COINCIDIRÁ com o de uma regra condicionada a on BeforeComplete.

Enquanto que a primeira se dispara ao sair do nível dos telefones, e antes de entrar a validar todos os emails, a segunda se dispararádepois de sair deste último nível.Neste caso o evento BeforeComplete coincidirá com o AfterLevel Level CustomerEMail.

Evento de disparo: AfterComplete

Este evento corresponde ao instante de tempo que acontece o commit. Falaremos mais deste evento umas páginas adiantes, quando estudarmos integridade transacional.Se abrir a transação de faturas, se ingressam 3 faturas (cabeçalho e suas respectivas linhas) e fecha a transação, ocorrerão 3 commits (um no final de cada ingresso de cabeçalho + linhas) e 3 eventos AfterComplete.

Page 129: 93909254 GENEXUS Heuristica Apostila Teorica

REGRAS STAND-ALONE

AVALIAÇÃO DE REGRAS EFÓRMULAS SEGUNDO

ÁRVORE

AVALIAÇÃO DE REGRAS EFÓRMULAS SEGUNDO ÁRVORE

PARA CADA LINHA

Interativamente e antes de confirmar:

Exemplo em uma transação de 2 níveis

O seguinte exemplo pretende mostrar visualmente em que momentos serão disparadas as regras e fórmulas definidas numa transação.

O disparo de regras e fórmulas irá sendo feito de acordo com a árvore de avaliação, seguindo a ordem que esta determina.

Page 130: 93909254 GENEXUS Heuristica Apostila Teorica

REGRAS STAND-ALONE

AVALIAÇÃO REGRAS E FÓRMULAS SEGUNDO ÁRVORE

AfterValidate / BeforeInsert / Update / DeleteGRAVAÇÃO DO CABEÇALHOAfterInsert / Update / Delete

AfterValidate/BeforeInsert/Udpate/DeleteGRAVAÇÃO DA LINHAAfterInsert/Update/Delete

AfterLevel Level attNivel2 - BeforeComplete

AfterCompleteCOMMIT

VALIDAÇÃO

AVALIAÇÃO DE REGRAS EFÓRMULAS SEGUNDO ÁRVORE

PARA CADA LINHA

Ao confirmar os dados, na seguinte ordem são executados:

VALIDAÇÃO

ABANDONAR NÍVEL 2

BeforeValidate

BeforeValidate

Exemplo em transação de 2 níveis

Regras stand aloneAs regras stand alone são aquelas que:1. Podem executar-se com a informação prevista pelos parâmetros recebidos.2. Não dependem de nada para serem executadas.

Exemplos de regras stand alone (poder executar com a informação prevista pelos parâmetros):· &A = parâmetro2;· Msg( ‘...’ ) if parâmetro1 = 7;

Exemplos de regras stand alone (não dependem de nada para serem executadas) :· msg( ‘You are in the invoice transaction’);· &A = 7;

Portanto, são as primeiras regras que podem ser executadas.Depois da execução das regras stand alone, se executam as regras associadas ao primeiro nível da transação, que não tenham evento de disparo definido, seguindo a ordem de dependências determinado por GeneXus (assim como as fórmulas associadas ao primeiro nível). Como exemplo, se dispara a regra: “Default( InvoiceDate, &Today);”Depois de executadas as regras mencionadas para o cabeçalho, serão executadas todas as regras que tenham como evento de disparo BeforeValidate, já que imediatamente depois ocorre a ação de validação (ou confirmação) da informação desse primeiro nível.

Imediatamente depois da validação do primeiro nível se executam as regras associadas ao primeiro nível da transação que incluam em sua definição o evento de disparo AfterValidate, ou os BeforeInsert, BeforeUpdate, BeforeDelete, dependendo do modo em que esteja.

Por exemplo: Se não podemos serializar as faturas com a propriedade Autonumber porque o DBMS escolhido não suporta:

InvoiceId = PGetNumber.udp(‘INVOICE’) on BeforeInsert;

Page 131: 93909254 GENEXUS Heuristica Apostila Teorica

Após a execução das regras associadas ao primeiro nível com alguns destes eventos de disparo executa-se a ação de gravação; ou seja, que gravará fisicamente a instancia correspondente ao primeiro nível da transação como registro físico na tabela correspondente (neste exemplo, na tabela: INVOICE).Imediatamente depois de ter gravado a instancia:· se a gravação correspondeu a uma inserção: executarão as regras associadas ao primeiro nível da transação com evento de disparo AfterInsert.· se a gravação correspondeu a uma atualização: executarão as regras associadas ao primeiro nível da transação com evento de disparo AfterUpdate.· se a gravação correspondeu a uma eliminação: executarão as regras associadas ao primeiro nível da transação com evento de disparo AfterDelete.

Sendo uma transação de dois níveis, como neste caso, serão executadas para cada uma das linhas:

Em primeiro lugar, as regras associadas ao segundo nível da transação que não tenham evento de disparo

definido, seguindo a ordem de dependências determinado pelo GeneXus (assim como as fórmulas

associadas ao segundo nível). Exemplos disso são a regra:

Subtract( InvoiceDetailQuantity, ProductStock );

a fórmula

InvoiceDetailAmount = InvoiceDetailQuantity*ProductPrice.

Depois das regras mencionadas executadas para uma linha, serão executadas todas as regras que tenham como evento de disparo BeforeValidate, visto que imediatamente depois ocorre a validação da linha; isto éuma ação que ocorre depois de terminar de trabalhar com a linha.

Imediatamente depois da validação da linha, serão executadas as regras associadas ao segundo nível da transação que incluam em sua definição algum dos eventos de disparo: AfterValidate, BeforeInsert,

BeforeUpdate, BeforeDelete.

Em seguida a execução das regras associadas ao segundo nível com algum destes eventos de disparo seráexecutada a ação de gravação; isto é, gravará fisicamente a instancia correspondente a linha como registro física na tabela correspondente (neste exemplo, na tabela: INVOICEDETAIL).

Imediatamente depois de ter gravado a instancia correspondente a linha como registro físico na tabela correspondente:

• se a gravação correspondeu a uma inserção: são executadas as regras associadas ao segundo nível da transação com evento de disparo AfterInsert.• se a gravação correspondeu a uma atualização: são executadas as regras associadas ao segundo nível da transação com evento de disparo AfterUpdate.• se a gravação correspondeu a uma eliminação: são executadas as regras associadas ao segundo nível da transação com evento de disparo AfterDelete.

Todas estas operações sombreadas de cinza claro, são executadas na ordem descrita, para cada uma das linhas.

Após a interação de todas as linhas, podemos supor a existência de uma ação que poderíamos chamar abandono do segundo nível. Após dela são executadas as regras definidas com evento de disparo AfterLevel Level Atributo do 2do nível. Se não existir outro nível, como é o caso do exemplo, então coincidirá com o evento de disparo BeforeComplete

Page 132: 93909254 GENEXUS Heuristica Apostila Teorica

Declaração Importante: Todas as operações sombreadas, tanto de cor clara como de cor escura, executam-se unicamente quando for uma transação de dois níveis; de modo que se for uma transação de um nível, sabemos que tais operações não são executadas. O motivo dos dois sombreados distintos, é para diferenciar o conjunto de operações que são executadas para cada uma das linhas (sombreado cor clara) das operações que são executadas somente uma vez ao terminar de interagir com as linhas (sombreado com cor mais escura). Posteriormente, explicaremos as demais operações que são executadas, seja em uma transação de um nível ou de dois.

Após de ser executada todas as operações explicadas até o momento, um commit é efetuado.

Na continuação serão executadas as regras com evento de disparo AfterComplete.

É de fundamental importância que fique claro que todas as operações explicadas, serão executadas na ordem que foi descrito, para cada fatura com a qual se trabalhe por meio da transação “Invoice” (seja quando se insere,

modifique ou elimine)

Pode ser útil saber que serão ressaltadas em negrito as ações cada vez que se tenha mencionado. As mesmas são: validação, gravação, abandono do segundo nível (sair do segundo nível) e commit.

É indispensável assimilar fortemente em que ordem se executam as regras em uma transação, quais são os eventos de disparo disponíveis para atribuir, quando são disparadas exatamente, e que ações ocorrem antes e depois de cada evento de disparo, já que somente conhecendo bem todo este tema, poderá programar o comportamento das transações adequadamente. É fácil compreender que se necessitamos programar determinados controles ou ações nas transações, teremos que saber bem se será feito antes de gravar o cabeçalho, depois de gravar o mesmo, para cada uma das linhas depois que se tenham gravado, ou antes, depois do commit, ou antes, portanto é fundamental ter bem claro todo este tema.

Page 133: 93909254 GENEXUS Heuristica Apostila Teorica

Exemplos

Quando são disparadas as regras seguintes?

• Something.call( InvoiceId ) if Insert;

• Something.call( InvoiceId ) on BeforeInsert;

• Something.call( InvoiceId, ProductId ) on BeforeInsert;

• Something.call( InvoiceId ) on BeforeInsert Level ProductId;

Depois de validar o campo InvoiceId e inferido que se está em modo Insert

Depois de disparar todas as regras e fórmulas segundo árvore, e validar todos os dados do cabeçalho. Ocorre um instante antes do registro ser inserido.

Depois que todas as regras e fórmulas segundo a árvore serem disparadas, e validados todos os dados da linha. Ocorre um instante antes de inserir o registro.

Idem ao anterior. Observar que Level ProductId especifica que se estáfalando do BeforeInsert das linhas e não do cabeçalho.

Page 134: 93909254 GENEXUS Heuristica Apostila Teorica

Exemplos

Algumas regras estão mal programadas. Quais?

• InvoiceDate = &today on AfterInsert;

• Something.call( InvoiceDate ) on AfterInsert;

• Something.call( InvoiceId, ProductId ) on AfterLevel Level ProductId;

Incorreto: O último momento para atribuir valor a um atributo do cabeçalho é imediatamente antes de sua gravação (BeforeInsert)

Correto: aqui está sendo passado o valor de um atributo do cabeçalho; enquanto estiver na instância da fatura esse valor está na memória. Último momento possível para utilizá-lo é no AfterComplete.

Incorreto: a regra, o evento de disparo está associada ao 2do. Nível, isto é, é disparado para cada linha. Mas o evento de disparo condiciona que seja executada ao sair das linhas. Qual valor teria ProductId?

Page 135: 93909254 GENEXUS Heuristica Apostila Teorica

Regras com o mesmo evento de disparo

• São disparadas na ordem em que foram definidas

• Exemplo 1‘xxx’.call() On AfterComplete;‘yyy’.call() On AfterComplete;

• Exemplo 2‘pgmname’.call( CustomerId, &flag) On AfterComplete;error(' ') if &flag = 'N’ On AfterComplete;

Regras com o mesmo evento de disparoQuando em uma transação definimos duas ou mais regras com o mesmo evento de disparo, e não existe nenhuma dependência entre elas, as mesmas serão executadas respeitando a ordem de definição.

Exemplos:1) Se definem as seguintes regras em uma transação:‘xxx’.Call() on AfterComplete;‘yyy’.Call() on AfterComplete;

Como as duas regras definidas estão condicionadas ao mesmo evento de disparo, e não existe nenhuma dependência entre elas, elas serão executadas na mesma ordem em que foram escritas.

2) Em uma transação, caso seja necessário chamar a um procedimento que realiza determinada validação e retorna um valor ‘S’ ou ‘N’; e se o valor devolvido é ‘N’, aparecerá uma mensagem de erro.

Para resolver isto, avaliaremos duas possibilidades:2.1) Definir as regras:Pgmname.call(CustomerId, &flag) on AfterComplete;Error(“ “) if &flag=”N” on AfterComplete;

Page 136: 93909254 GENEXUS Heuristica Apostila Teorica

2.2) Ou definir as regras:&flag = Pgmname.udp(CustomerId) on AfterComplete;Error(“ “) if &flag = ”N” on AfterComplete;

Na primeira alternativa, temos definida uma regra call e uma regra error. Ambas regras tem o mesmo evento de disparo, e aparentemente existiria dependência entre elas, já que a regra de error está condicionada ao valor da variável &flag, e a variável &flag se passa por parâmetro na regra call.

Todavia, a dependência pode parecer evidente porque no procedimento programamos a variável &flag, de saída, na seção de regras da transação - que é onde encontram-se as regras vista até então -, o especificador do GeneXus não pode saber se os parâmetros passados em um call são de entrada, de saída, ou de entrada-saída; em conseqüência o especificador não encontrará inter-dependência entre as regras calle error, já que a variável &flag poderia ser passada como variável de entrada ao procedimento, e nesse caso por Exemplo, não haveria uma dependência de que primeiro deve-se executar a regra call e depois a regra error.

Concluindo, não se detectam dependências entre as regras call e error da alternativa 2.1), porque as mesmas serão disparadas na Ordem em que estão escritas. É importante ver que, se as regras call e errorestiverem escritas em ordem inversa (primeiro a regra error e depois a regra call), em muitos casos o comportamento não será o esperado.

A respeito da segunda alternativa, observemos que consiste em uma regra udp e uma regra error. Ambas regras tem o mesmo evento de disparo, e neste caso se existir dependência entre elas, já que a regra errorestá condicionada ao valor da variável &flag, e como as chamadas ao procedimento realizam-se com udp, para o especificador do GeneXus fica claro que a variável &flag volta modificada do procedimento; portanto, o especificador do GeneXus entende que primeiro deve-se disparar a chamada ao procedimento com udp e depois a regra error, porque a variável &flag é carregada mediante a chamada ao procedimento com udp, e logo que esta variável tenha valor, é que será avaliada a necessidade de disparar a regra error, ou não.

No caso 2.2), então, independentemente da ordem de definição de ambas as regras, a chamada ao procedimento com udp é disparada primeiro, e em seguida dispara a regra error (caso cumpra-se a condição de disparo).

Por esta razão recomendamos que sempre que se quer definir validações desse tipo, se utilize udp ao invés de call.

Page 137: 93909254 GENEXUS Heuristica Apostila Teorica

Eventos em Transações

Nas transações permite-se a programação dirigida por eventos, que é um estilo de programação na qual se define código que permanece ocioso, até que os eventos provocados pelo Usuário ou pelo sistema, provoquem que o código definido seja executado.

Os eventos são ações reconhecidas por um objeto que podem acontecer ou não. A cada evento podemos associar o código, que será executado somente caso o evento se produza.

O código que pode ser associado a um evento, é escrito de forma procedural; e quando o evento for produzido, o código associado ao mesmo será executado seqüencialmente.

Page 138: 93909254 GENEXUS Heuristica Apostila Teorica

Eventos em Transações

• Evento Start

• Evento ‘User Event’

• Evento After Trn

• Evento Exit

• Evento TrackContext

Como em Web não se mantém um estado no servidor que permita saber o que está sendo executado no cliente, não é possível saber se está ingressando a primeira instancia de uma fatura, ou se é a n-ésima. Por esta razão, se disparará o evento Start cada vez que se envie ao servidor a informação da instancia com a qual estiver trabalhando.

Enquanto que no evento Exit, se excuta por cada iteração, ao final da mesma.

O evento TrackContext é aplicado para obter interfaces de usuário sensíveis ao contexto. Programando este evento pode-se receber informação do contexto para depois tomar as decisões necessárias.

Page 139: 93909254 GENEXUS Heuristica Apostila Teorica

Eventos Start

• Start: Executado cada vez que o form de uma transação ésubmetido ao servidor.

Event Startcódigo

EndEvent

EXEMPLO: Event Start&entrada=Now()

EndEvent

SINTAXE:

O evento Start é um evento do sistema, ocorre automaticamente.

EXEMPLO:Em uma transação nos interessa capturar a data e hora de entrada da mesma. Para isso no evento Start o atribuímos a uma variável de nome &entrada e tipo de dados DateTime, o resultado da função Now() que devolve a data e hora atual:

Event Start&entrada = Now()

EndEvent

Se executa cada vez que se submeta o form da transação, ou seja, quando o usuário pressionar qualquer botão do form.

Notas gerais:No evento Start fundamentalmente se trabalha com variáveis. Já a utilização dos atributos neste evento, seja para avaliá-los e/ou usá-los de algum modo exceto para atualizá-los, se deve considerar que os únicos atributos que estão disponíveis são os que são recebidos por parâmetro na regra parm. Nenhum outro atributo terá valor neste evento, pois todavia não foi editado a instancia da transação.

Page 140: 93909254 GENEXUS Heuristica Apostila Teorica

Eventos de Usuário

• Além dos eventos oferecidos por GeneXus, o analista pode definir eventos criados por ele, chamados eventos de usuário.

Web: Ordem de execução

1. Evento Start2. Leitura de atributos e variáveis do form3. Evento de usuário selecionado

Propriedades

Como pode-se observar na sintaxe, deve-se dar um nome a um evento do usuário, após a palavra Event, que encontra-se entre aspas simples.

EXEMPLO:

Se deseja que na transação "Invoice", o usuário possa imprimir a fatura com a qual esteja trabalhando, pressionando F7 (isto somente é válido para Win):

Event ‘Print Invoice’ // evento definido na transação "Invoice"PrintInvoice.Call( InvoiceId )

EndEvent

Como associar um evento de usuário a um controle?

Além dos botões, também as imagens e os text blocks admitem a associação de evento de usuário. Para realizar a associação se deve inserir o controle correspondente no form Web e depois nas propriedades do controle, selecionar onde diz OnClickEvent um dos eventos existentes, ou se pode criar um novo.

Page 141: 93909254 GENEXUS Heuristica Apostila Teorica

Evento After Trn

• Ocorre imediatamente depois da execução das regras com evento de disparo AfterComplete.

• Sintaxe:

• Exemplo: Event After trnReturn

EndEvent

Event After Trn código

Endevent

O evento After Trn das transações ocorre imediatamente depois da execução das regras com evento de disparo AfterComplete. Em seguida, o código incluído neste evento, será executado depois que termine cada interação completa por meio da transação (assim que é gravado cada cabeçalho com suas correspondentes linhas como registros físicos nas tabelas que corresponda e de se ter efetuado o COMMIT).

Existem as seguintes alternativas para programar comportamentos que desejam ser executados no final de cada interação completa por meio de uma transação:

1. Definir regras individuais com evento de disparo AfterComplete e deixar o evento After Trn sem código2. Definir todas as sentenças no evento After Trn com estilo procedural, e não definir regras com evento de disparo AfterComplete3. Definir as duas coisas: algumas regras com evento de disparo AfterComplete e código no evento After Trn

Como vemos explicando, primeiro são executadas as regras definidas com evento de disparo AfterComplete, e imediatamente após, executamos as regras com código definido no evento After Trn.

Um conceito que é muito importante ter claro é que tanto nas regras com evento de disparo AfterComplete como no evento After Trn, os valores dos atributos do primeiro nível da transação são conhecidos.

Ou seja, serão gravados fisicamente os registros correspondentes ao cabeçalho e as linhas de certa interação completa, inclusive se efetuou COMMIT, ainda temos disponíveis os valores dos atributos do primeiro nível, podendo ser utilizados para passar por parâmetro em uma chamada, ou avaliar seu valor, ou usar de algum modo, exceto atualizá-los ¹. ________________________________________________________________________________1 Existem dois motivos pelos quais não é possível atualizar atributos em regras com evento de disparo AfterComplete e After Trn. O primeiro motivo é que já foi realizado as gravações correspondentes e incluso o COMMIT já foi realizado, de modo que já é tarde para atribuir valores aos atributos. Além disso, relacionado ao evento After Trn, nos eventos não é permito realizar atribuições aos atributos.

Page 142: 93909254 GENEXUS Heuristica Apostila Teorica

Não é permitido atribuir valores a atributos nos eventos.

Os valores dos atributos podem ser modificados nas transações:· o usuário final fazendo, em tempo de execução, através do form (somente atributos das tabelas bases associadas a transação, ou aqueles da estendida permitidos pela regra update)· mediante regras definidas pelo programador (a atributos das tabelas bases associadas a transação e suas estendidas)

Os eventos Start e Exit são sem tabela base. Com esta expressão nos referimos que nos eventos Start e Exit não tem consulta ativa à base de dados (já que no evento Start ainda não foi feito a consulta e no evento Exit em Win já foi fechado o programa associado a transação e em Web a instancia está sendo fechada e já não dispõe da consulta). Por este motivo é que não conhecemos valores de atributos nos eventos Start e Exit, exceto os recebidos por parâmetro.

Ao contrário, os eventos After Trn e de Usuário são com tabela base, quando os mesmos se executam temos uma consulta feita. Então, em particular no evento After Trn, conhecemos os valores dos atributos do primeiro nível (o segundo nível já foi inserido a essa altura e não tem possibilidade de posicionamento em alguma linha em particular); e no que diz respeito aos eventos de Usuário os atributos de todos os níveis 1

estão disponíveis.

É fundamental que fique claro, que assim que se disponha dos valores de certos atributos ou outros dependendo do evento, os mesmos poderão ser utilizados para ser analisados e/ou passados por parâmetro a objetos que se chamem, e/ou para alguma outra operação qualquer que não seja atribuir valor.

Concluindo, em nenhum evento (não somente das transações, mas em nenhum objeto GeneXus) permite-se realizar atribuições a atributos.

________________________________________________________________________________________________________________________

1 Se num evento de usuário são referenciados atributos de um segundo nível ou outro nível subordinado, quando o evento de usuário for executado nos atributos daquela linha se tem um posicionamento; no momento que o evento de usuário é executado serão considerados os valores dos atributos desta linha. Caso o usuário não se posicionou explicitamente em determinada linha, por default a linha que selecionada é a primeira linha, assim serão estes os valores dos atributos considerados.

Page 143: 93909254 GENEXUS Heuristica Apostila Teorica

143

Integridade Transacional

IT

Page 144: 93909254 GENEXUS Heuristica Apostila Teorica

144

O que é o conceito: integridade transacional?

• É um conjunto de atualizações de integridade transacionalque a base de dados possui quando acontece uma finalização “anormal”, a base de dados permanece em estado consistente.

Muitos administradores de bases de dados (DBMSs) contam com sistemas de recuperação anti-falhas, que permitem deixar a base de dados em estado consistente quando ocorrem imprevistos tais como apagões ou quedas do sistema.

Page 145: 93909254 GENEXUS Heuristica Apostila Teorica

145

• Uma Unidade Lógica de Trabalho (UTL) é um conjunto de operações na base de dados, todas devem ser executadas ou nenhuma delas.

O que é o conceito:unidade lógica de trabalho (UTL)?

Os administradores de bases de dados (DBMSs) que oferecem integridade transacional, permitem estabelecer Unidades Lógicas de Trabalho (UTLs), que são, nem mais nem menos, que o conceito de transações de base de dados.

Page 146: 93909254 GENEXUS Heuristica Apostila Teorica

146

O que é efetuar COMMIT?

• O comando COMMIT permite especificar que certo conjunto de operações realizadas sobre uma base de dados que foram efetuadas corretamente:

...........Operação sobre Base de DadosOperação sobre Base de Dados

Finaliza UTLComeça UTLOperação sobre Base de DadosOperação sobre Base de DadosOperação sobre Base de DadosOperação sobre Base de Dados

Finaliza UTL

• Efetuar COMMIT em uma base de dados, significa finalizar uma Unidade Lógica de Trabalho (UTL).

COMMIT

COMMIT

Efetuar COMMIT em uma base de dados, significa finalizar uma Unidade Lógica de Trabalho (UTL).

Page 147: 93909254 GENEXUS Heuristica Apostila Teorica

147

O que é efetuar ROLLBACK?

• Fazer ROLLBACK (voltar atrás) implica em desfazer todas as operações efetuadas na base de dados que não tenham recebido COMMIT.

• Isto resolve-se desfazendo todas as operações posteriores ao último COMMIT.

Page 148: 93909254 GENEXUS Heuristica Apostila Teorica

148

Unidade lógica de trabalho (UTL)por default em GeneXus

�Todo objeto GeneXus transação e todo objeto GeneXus procedimento, é por default uma Unidade Lógica de Trabalho (UTL).

�Ou seja, as transações e procedimentos são os únicos objetos GeneXus (*) que permitem atualizar a base de dados, e por default o GeneXus inclui nos programas gerados associados aos mesmos, a sentença COMMIT.

�No objeto procedimento GeneXus incluiu um COMMIT automático no final do Source.

�No objeto transação GeneXus incluiu um COMMIT automático no final de cada instancia, imediatamente antes das regras com evento de disparo AfterComplete

(*) uma exceção Business Components, mas o commit não é realizado automaticamente.

É importante comentar que o GeneXus inclui a sentença COMMIT nos programas gerados associados a transações e procedimentos, somente em ambientes de trabalho Cliente/Servidor (incluindo, portanto, os ambientes Web). O motivo disto é que em ambientes Cliente/Servidor, temos um DBMS que assegura aintegridade transacional, portanto o GeneXus efetua a tarefa de definir as Unidades Lógicas de Trabalho (UTLs).

Onde o GeneXus inclui COMMIT exatamente?

Em cada procedimento: ao final do programa fonte.

Em cada Transação: imediatamente antes das regras com evento de disparo AfterComplete. Para cada interação completa que for efetuada em tempo de execução por meio da transação, haverá um COMMIT, antes das regras com evento de disparo AfterComplete.

Nota: o novo tipo de dados Business Component que estaremos vendo depois permite atualizar a base de dados desde qualquer objeto GeneXus, mas será visto que não realiza automaticamente um COMMIT.

Page 149: 93909254 GENEXUS Heuristica Apostila Teorica

149

• Propriedade Commit on Exit de transações e procedimentos:

Valores:

• Yes (Default): COMMIT é executado

• No: COMMIT Não é executado

Personalização de UTL em GeneXus

GeneXus oferece uma Propriedade para cada objeto transação e procedimento, para definir se deseja que seu programa gerado efetue ou não o COMMIT. O nome da Propriedade é Commit on Exit e seu valor por default é Yes (por isso, toda transação e procedimento por default efetua COMMIT).

Se desejamos que certa transação ou procedimento não tenha COMMIT no programa gerado, alterar o valor da Propriedade Commit on Exit para No.

Page 150: 93909254 GENEXUS Heuristica Apostila Teorica

150

Trn. “X”

Commit on Exit = No

Proc. “Y”

• Exemplo de Commit on Exit = No

call

Importante: chamar a partir da Trn. “X” ao Proc. ”Y” utilizando um evento de disparo que consideremos adequado e que ocorra antes da execução do COMMIT da Trn “X”.

Commit on Exit = Yes

Personalização de UTL em GeneXus

Por que motivo pode-se querer que não seja realizado COMMIT em uma Transação ou Procedimento?Para personalizar uma Unidade Lógica de Trabalho (UTL). Isto é, podemos precisar ampliar uma Unidade de Trabalho Lógica (UTL), para que várias transações1 e/ou procedimentos, estejam em uma única Unidade de Trabalho Lógica (UTL).

Exemplo (mostrado acima):A Transação “X” chama um Procedimento “Y”, e deseja-se que ambos objetos estejam em única UTL. A Transação atualiza certos registros, e o procedimento outros, e se deseja que esse conjunto total de operações, consista em uma única UTL (para assegurarmos que se ocorrer alguma falha, seja realizado todo o conjunto de atualizações ou nada na da base de dados).

Para isto, podemos eliminar o COMMIT do procedimento, e deixar que seja realizado na Transação (ao retornar do procedimento para a Transação, para que seja executado ao final de todas as operações); temos que configurar a propriedade Commit on Exit do procedimento com valor: No e deixar a propriedade Commit on Exit da Transação com o valor por default: Yes. Mas além disso, é fundamental que a chamada ao procedimento seja realizada antes que se execute o COMMIT na transação (jáque a idéia é que ambos os objetos tenham uma única UTL, e para ele o COMMIT deve efetuar na transação ao retornar do procedimento); assim que a chamada ao procedimento definir na Transação com um evento de disparo que ocorra antes da execução do COMMIT (dependendo se a transação tiver um nível ou mais, e dos requerimentos, poderia ser AfterInsert por exemplo, AfterUpdate, ou AfterLevel Level Atributo do 2do nível, ou BeforeComplete mas não AfterCompete).

Não existe uma única solução para personalizar uma UTL. O fundamental é analisar qual objeto pode fazer COMMIT (podendo haver mais de uma possibilidade) e uma vez que se decida qual objeto efetuaráCOMMIT, as chamadas que se requerem fazer, deverão ser efetuadas em momentos adequados, considerando se já executou o COMMIT ou não.____________________________________________________________________________

¹ Em ambiente Web existe uma restrição importante: se uma transação chamar outra transação, o Commit realizada por uma não aplica sobre os registros ingressados/modificados/eliminados pela outra. Isto é, o Commit de cada transação contém somente “visibilidade” sobre os registros operados por essa transação, e não por outra, onde duas transações diferentes não podem ficar em uma mesma UTL. Não poderá realizar-se personalização neste caso.

Page 151: 93909254 GENEXUS Heuristica Apostila Teorica

151

Por Exemplo, para que a transação e procedimento vistos conformem uma única UTL, poderíamos ter optado também pela alternativa de que não efetue COMMIT na transação (Commit on Exit = No), mas sim que seja realizado pelo procedimento ao final de tudo; fazer dessa forma, não seria um erro - como o é na solução anterior - chamar ao procedimento utilizando o evento de disparo AfterComplete, o COMMIT não será realizado na transação, mas no procedimento.

Concluindo, precisamos decidir qual objeto fará COMMIT e que as chamadas necessárias sejam feitas em momentos adequados, para que a UTL personalizada fique bem definida.

Outro Exemplo:A transação “Invoice“ estudada até o momento, em um modelo de Protótipo cliente/servidor. Caso não modificarmos o valor predeterminado da propriedade Commit on Exit.E o usuário executa a transação, inserindo a fatura 1 e todas as suas linhas. Depois insere a fatura 2 e quando inserir a 3era. Linha da mesma ocorre um apagão. Quando a energia volta e reinicializa a execução, quais os registros que ficaram gravados na tabela e quais foram perdidos?

A fatura 1 inteira estará gravada (cabeçalho e suas linhas). Por quê? Porque ao terminar de inserir e passar a inserir a fatura 2, foi efetuado um commit. A fatura 2 com os registros que gravou até o momento que faltou energia, foi perdido. Por quê? Porque a transação realiza o rollback de tudo que foi efetuado depois do último commit. O cabeçalho da fatura 2 e as suas linhas informadas não estavam ainda “commitadas”.

Observar então que o commit não é pela transação inteira (ou seja, todas as interações do cabeçalho e suas linhas) e sim por cada instancia do cabeçalho e linhas. Se o commit acontece uma única vez antes da transação ser fechada, então se tivesse sido ingressados 29 faturas e o sistema caísse na trigésima, todas as 29 faturas anteriores (todo o processo seria desfeito, já que ainda não foi realizado o commit). Isto não é assim, quando ocorre a queda do sistema na trigésima fatura informada, ficaram gravadas as 29 anteriores (só não foi à trigésima).

Page 152: 93909254 GENEXUS Heuristica Apostila Teorica

152

Trn.“X”

• Uma UTL composta por várias transações Web não pode ser definida

call

Personalizaçã de UTL

• Uma transação Web somente pode ter Commit dos registros inseridos por ela mesma, ou pelo procedimento em uma cadeia de chamadas, porém não pode fazer um Commit dos registros inseridos por outra transação.

Trn.”Y”

Trn.“X”

call

(depois do

Commit)

Trn.”Y” Proc.”Z”

call

(antes do

Commit)

UTL

Não podem ficar dentro de uma mesma UTL

UTL 1 UTL 2

Em ambiente Web os registros “visíveis” para ser commitados por uma transação são os atualizados pela própria transação, e pela própria transação, e pelos procedimentos que esta chame antes do seu Commit, porém não os de outra transação.

Cada transação trabalha com diferentes UTLs.

É por este motivo que no primeiro exemplo acima apresentado, onde a transação “X” chama a transação “Y” logo de ter inserido um registro, embora a transação “Y” realize um Commit ao final do cabeçalho e linha são ingressadas, este Commit não valerá sobre o registro que teria sido ingressado previamente pela transação “X”. Este registro ficará “perdido”, sem Commit.

Internet trabalha de forma diferente, as transações Web “vivem” somente o tempo em que o usuário de um navegador seleciona o link ou pressiona um botão e a nova página é mostrada. Toda modificação da base de dados que se faça durante a “vida” da transação deve ser confirmada ou eliminada antes que a transação Web finalize sua execução e retorne à página resultante.

Como conseqüência, uma transação Web inicia uma UTL (Unidade Lógica de Trabalho) ao começar a executar e fecha-a (seja por COMMIT ou ROLLBACK) antes de terminar. Não pode formar parte de outra UTL. Se um programa chama uma transação Web, esta iniciará outra (nova) UTL.

Não acontece isso com os procedimentos. No segundo exemplo mostrado acima, vemos que podemos formar uma UTL que envolva à transação “Y” e ao procedimento “Z”...com tudo não podemos incluir a transação “X” na mesma UTL.

Page 153: 93909254 GENEXUS Heuristica Apostila Teorica

153

• Se desejarmos ter uma mesma UTL para duas transações diferentes:

Solução: utilizar Business Components e o comando Commit após inserir variáveis Business Components dos registros associados a ambas transações (será visto mais adiante).

Personalização de UTL

Trn.“X” Trn.”Y”

Caso seja necessário que as operações de duas ou mais transações (com ou sem procedimentos incluídos) estejam em uma mesma UTL, pode-se usar as transações com Web Panels e Business Components; e utilizar o comando Commit.

Aqui simplesmente vamos deixar o tema sinalizado, voltaremos nele após estudar Business Components, onde vamos compreender esta solução.

Page 154: 93909254 GENEXUS Heuristica Apostila Teorica

154

• GeneXus oferece os comandos: COMMIT e ROLLBACK

• Podem ser incluído em Procedimentos e Web Panels, assim como combinados com Business Components.

• Exemplo (usuário final decide executar Commit ou Rollback): A partir de uma transação é chamado vários procedimentos consecutivos, e a todos eles se configura a propriedade Commit on exit = No… e no último procedimento se pergunta ao usuário se confirma; dependendo da resposta do usuário, terá que executar o comando COMMIT ou ROLLBACK

Comandos COMMIT e ROLLBACK de GeneXus

Page 155: 93909254 GENEXUS Heuristica Apostila Teorica

155

Objeto Procedimento

Page 156: 93909254 GENEXUS Heuristica Apostila Teorica

156

Procedimentos

Definição

• Processos não interativos de consulta e atualização da base de dados.

Procedimentos:Definem processos não interativos de consulta e atualização da base de dados. Os procedimentos podem gerar um arquivo formato PDF, mediante o qual é possível listar informação na tela ou impressora. Além disso, os procedimentos podem atualizar a base de datos1.

__________________________________________________________________________

1 Como veremos mais adiante, existe um tipo de dados especial, que não é estritamente um tipo de dados, mas algo um pouco mais complexo, o business component, por meio do qual serão realizados atualizações a base de dados em qualquer objeto GeneXus. Portanto, utilizando variáveis de tipo de dados business component, poderão ser realizadas atualizações incluso nos objetos que por natureza não oferecem esta possibilidade, como as web panels.

Page 157: 93909254 GENEXUS Heuristica Apostila Teorica

157

Características

• Definição procedural

• Definição sobre a base de conhecimento

• Independência da base de dados: definição a nível de atributos

Definição procedural

A diferença das regras das transações onde as especificações se realizam de forma declarativa e GeneXus determina no momento de gerar o programa a seqüência de execução, nos procedimentos as especificações se realizam de forma procedural. Desta forma, a seqüência de execução édeterminada pelo analista, utilizando para isso uma linguagem simples que contem comandos de controle, de impressão, de acesso a base de dados, etc.

Definição sobre a base de conhecimento

A grande potencia da linguagem dos procedimentos está que as definições são realizadas sobre a base de conhecimento e não diretamente sobre o modelo físico (tabelas, índices, etc.). Isto nos permite utilizar automaticamente todo o conhecimento já incorporado ou gerado por GeneXus a partir das especificações realizadas.

Por exemplo, se desejamos mostrar o resultado de uma fórmula é suficiente nomear o atributo fórmula no lugar adequado e GeneXus dispara o cálculo mostrando o resultado, sem necessidade do analista oferecer nenhuma outra informação. A informação de como se calcula um atributo fórmula está contida na base de conhecimento.

Também podemos utilizar o conceito de tabela estendida, já que GeneXus conhece as relações entre as tabelas da base de dados, o analista não precisa explicitar estas relações na hora de recuperar dados.

Independência da base de dados: definição a nível de atributos

A definição dos procedimentos se faz a nível de atributos: não é necessário indicar explicitamente quais tabelas serão percorridas e nem mediante quais índices. Somente mencionando os atributos que deseja acessar é suficiente para que o GeneXus determine esta informação. Isto é possível porque GeneXus possui um completo conhecimento da estrutura da base de dados.

Desta maneira obtemos uma real independência da base de dados, já que qualquer alteração nas tabelas será gerenciado automaticamente pelo GeneXus e desta forma, para atualizar os programas alcança em grande parte das vezes, como regerar os objetos sem ter que modificar nada do programado neles.

Page 158: 93909254 GENEXUS Heuristica Apostila Teorica

158

Elementos

• Assim como nas transações, variáveis podem ser definidas e são locais ao objeto.

Para cada procedimento se pode definir:

• Source: Aqui se escreve o código correspondente a lógica do procedimento. Também podem definir-se ao final do código subrotinas1 que podem ser chamadas a partir do próprio código mediante o comando adequado.

• Layout: Assim como as transações possuem uma tela (form), os procedimentos possuem um “layout” de saída. Nesta seção se define apresentação do procedimento: os dados que se quer listar e o formato da saída.

• Regras-Propriedades: Definem aspectos gerais do procedimento, como seu nome, descrição, tipo de saída (impressora, arquivo, tela), parâmetros que recebe o objeto, etc.

• Condições: Condições que devem cumprir os dados para ser recuperados (filtros).

• Variáveis: Variáveis locais ao objeto.

• Ajuda: Permite a inclusão de texto de ajuda, para ser consultado pelos usuários em tempo de execução, para o uso do procedimento. Pode ter uma ajuda para cada linguagem.

• Documentação: Permite a inclusão de texto técnico, para ser utilizado como documentação do sistema.

__________________________________________________________________________________

1 Não serão vistas no presente curso. Ver no Curso Não Presencial de GeneXus.

Page 159: 93909254 GENEXUS Heuristica Apostila Teorica

159

Exemplo

área com dados fixosárea com dados fixos

área com dados variáveis (acesso a base de dados)

• Queremos implementar a listagem abaixo:

Por exemplo, vamos supor que queremos implementar um procedimento para imprimir o identificador, nome e país de todos nossos clientes e queremos que a listagem saia como mostrada na figura.

Para isso, devemos identificar na saída da listagem das distintas áreas que o compõem. A cada uma delas a representaremos com um Printblock.

Os primeiros dois Printblocks ilustram no GeneXus tal qual as primeiras duas áreas pois contem unicamente textos, linhas, retângulos. Também poderíamos ter colocado estas duas áreas convertendo-as em uma e utilizando portanto um único Printblock.

O terceiro Printblock será o correspondente da área de dados variáveis da figura anterior, que representa informação que deve ser extraída da base de dados.O que queremos mostrar neste caso é o identificador e nome de cada cliente, junto com o nome do país ao que pertence. Esta informação é a representada pelos atributos CustomerId, CustomerName

e CountryName da base de conhecimento da aplicação, o terceiro Printblock conterá os três controles atributo CustomerId, CustomerName e CountryName.

Transformando as áreas em Printblocks, o Layout do procedimento ficará como o da figura na página seguinte.

Page 160: 93909254 GENEXUS Heuristica Apostila Teorica

160

Printblock

Layout

• Sucessão de Printblocks

• Não importa a ordem de definição

• Cada Printblock deve ter um nome único

• Somente são declarados, são chamados a partir do Sourcecom o comando “print” (Ex.: print header)

Nome de cada Printblock

O Layout de um procedimento será uma sucessão de Printblocks que não tem por que seguir a ordem em que deseja que apareçam na saída.

No exemplo anterior, o mesmo procedimento teria sido impresso se houvesse especificado os Printblocks na ordem inversa (ou em qualquer ordem).

Aqui simplesmente são declarados. A ordem que são executados fica determinado na seção Sourceque é a que contem a lógica do procedimento. A partir dali serão chamados mediante um comando específico para tal finalidade (o comando print).

Por esta razão, cada Printblock deve ter um nome único para poder ser referenciado depois a partir do Source.

No exemplo, para listar todos os clientes, o Printblock de nome “customer” deve ser chamado dentro de uma estrutura repetitiva no Source. Esta estrutura repetitiva é o comando For each que estudaremos depois.

Page 161: 93909254 GENEXUS Heuristica Apostila Teorica

161

Layout: Printblock

• Para definir os Printblocks temos os seguintes controles disponíveis:

• e para inserir um Printblock – botão direito sobre o layout e escolhemos Insert Printblock

O Printblock é um tipo de controle válido somente nos procedimentos, que é inserido e eliminado do Layout pelo analista, e que contem outros controles -atributos, textos, retângulos, linhas, etc.-, sendo estes últimos os que efetivamente especificam qual é o que se quer mostrar na saída.

Para inserir os controles no Form de uma transação contamos com uma toolbox. A mesma toolbox se utiliza para inserir os controles no Layout. De fato esta toolbox está disponível para todos os objetos GeneXus criados, e em cada caso terá os controles disponíveis segundo o tipo de objeto.

Para inserir um Printblock - botão direito em qualquer lugar do layout e selecionamos InsertPrintblock.

Como todo controle, o Printblock possui propriedades que podem ser configuradas pelo usuário. Em particular, tem a propriedade “Name”, muito importante visto que é o identificador do Printblock. Com este identificador é que o Printblock pode ser chamado a partir do Source para ser impresso.

Para acessar as propriedades de um Printblock, o selecionamos e pressionamos F4 ou View/Properties.

Page 162: 93909254 GENEXUS Heuristica Apostila Teorica

162

Source• Define a lógica do procedimento mediante programação

procedural

• Linguagem simples

• Comandos usuais de controle: If, Do-case, Do-while, For

• Comandos de impressão: Print, Header, Footer

• Comando de acesso e atualização da BD: For each, New, Delete

• Comandos para sair de um loop, abandonar o programa, chamar outro objeto, chamar uma subrotina, etc.: Exit, Return, Call, Do

Nesta seção se define a lógica do procedimento .

A linguagem utilizada para programar o código fonte dos procedimentos é muito simples, e consta de alguns comandos que veremos.

O estilo de programação é procedural – imperativo – o Source será uma sucessão de comandosonde a ordem é fundamental: a ordem em que estejam especificados corresponderá, exceto exceções, a ordem em que serão executados.

Existem, como em toda linguagem imperativa, comandos de controle para a execução condicional (if, do case), o repetitivo (do while, for), para chamar a outro objeto (call), para cortar as iterações dentro de um loop (exit) ou abandonar o programa (return), assim como também comandos específicos desta linguagem: para imprimir um Printblock do Layout (print), para acessar a base de dados (For each), para inserir novos registros em uma tabela (new), para chamar a uma subrotina (do), etc.

No final da sucessão de comandos que constitui o código geral ou principal do procedimento, podem definir-se subrotinas que podem ser chamadas (mediante o comando do) a partir do código geral. Não podem ser chamadas a partir de outro objeto (são locais).

Por sua importância, começamos estudando detalhadamente o comando de acesso a base de dados, fundamental na hora de recuperar a informação armazenada. Depois serão tratados brevemente os comandos de controle, que são comuns a todos as linguagens de programação imperativa, os comandos de atribuição e os de impressão.

Page 163: 93909254 GENEXUS Heuristica Apostila Teorica

163

Comando For each

• Utilizado para acessar a informação da base de dados.

• Com um For each se percorre uma tabela da base de dados: a tabela base do For each.

• Para cada registro dessa tabela pode ser feito algo com a informação associada. (Exemplo: imprimir)

• Todo comando For each termina com um Endfor

A definição do acesso a base de dados para recuperar a informação se realiza com um único comando: o comando For each1.

Usando o For each se define a informação que vai acessar. A forma de o fazer é baseada em nomear os atributos a utilizar.

Assim, com este comando se definem quais atributos são necessários em qual ordem vai ser recuperada, e GeneXus se encarrega de encontrar como fazer. Não se especifica de quais tabelas se devem obter, nem quais índices se devem utilizar para acessar a essas tabelas: isso GeneXus infere. Evidentemente isto nem sempre é possível, e em tais casos GeneXus dá uma série de mensagens de erro indicando por que não se podem relacionar os atributos envolvidos.

A razão pela qual não se faz referencia ao modelo físico de dados é porque desta maneira a especificação do procedimento é de mais alto nível possível, de tal forma que ante mudanças na estrutura da base de dados a especificação do mesmo se mantenha válida a maior parte das vezes.

Quando aparece um For each se está indicando que se quer recuperar informação da base de dados. Concretamente GeneXus sabe que com um For each se quer percorrer (ou navegar) uma tabela. Para cada registro dessa tabela, se quer fazer algo com a informação associada (ex: imprimir).

Portanto, todo comando For each possui uma tabela física associada: a tabela que será percorrida ou navegada. A esta tabela vamos chamar tabela base do For each.

___________________________________________________________________________

1 Quando estudarmos os business components veremos que utilizando seu método Load também se consegue consultar a base de dados.

Page 164: 93909254 GENEXUS Heuristica Apostila Teorica

164

Comando For each

• Exemplo: Listagem de clientes

• Layout:

• Source:

CUSTOMER COUNTRY

For eachprint customer

Endfor

Intuitivamente com este comando queremos listar identificador, nome e país de cada um dos clientes da base de dados. Ou seja, queremos percorrer à tabela CUSTOMER, e para cada cliente seja recuperado da tabela COUNTRY o nome do país ao qual pertence, imprimindo esta informação, junto com o identificador e nome do cliente. (Observar que a tabela COUNTRY pertence à estendida de CUSTOMER)

Como o GeneXus infere isto, só o que fizemos foi For each do exemplo informar os atributos que nos interessava mostrar?

Page 165: 93909254 GENEXUS Heuristica Apostila Teorica

165

Comando For each

• Tabela percorrida: CUSTOMER

• Tabela acessada para cada cliente: COUNTRY

• INTERPRETAÇÃO:

CUSTOMER COUNTRY

For each record in table CUSTOMERFind the corresponding CountryName in table COUNTRY

print customerEndfor

Dentro de todo For each navega-se - percorre ou itera - a tabela base, mas podemos acessar as tabelas que constituem sua tabela estendida para recuperar a informação, por pertencer a estendida está relacionada com cada registro da tabela base com que esteja trabalhando em cada interação (o conceito de tabela estendida é muito importante neste comando e sugerimos repassar sua definição).

É por isso que no For each do exemplo, a tabela base será CUSTOMER, e acessa “para cada”cliente, não somente os dados de seu registro, como também do registro associado na tabela COUNTRY (que está na estendida de CUSTOMER). Dizemos então que se percorre CUSTOMER e se acessa além disso a de COUNTRY para buscar o resto da informação requerida.

Como podemos ver claramente no exemplo apresentado, não apresentamos de forma explícita ao GeneXus esta informação. Não é necessário, já que o GeneXus conhece as relações entre as tabelas, e na base os atributos mencionados dentro do For each e pode encontrar sem necessidade de mais informações uma tabela estendida que os contenha.

A tabela base dessa estendida é escolhida como tabela base do For each.

Page 166: 93909254 GENEXUS Heuristica Apostila Teorica

166

Comando For each: determinação de tabela base

• O acesso a base de dados fica determinado pelos atributos que são utilizados dentro do comando For each.

• Para esse conjunto de atributos, GeneXus busca a mínima tabela estendida que os contenha.

• Sua tabela base será a tabela base do For each.

A tabela base correspondente a essa tabela estendida é chamada de tabela base do For eache será percorrida seqüencialmente, executando para cada registro o que for indicado nos comandos internos do For each.

Page 167: 93909254 GENEXUS Heuristica Apostila Teorica

167

Comando For each: determinação de tabela base

{CustomerId, CustomerName, CountryName} ⊂ est(CUSTOMER)

{CustomerId, CustomerName, CountryName} ⊂ est(INVOICE)

Mas:est(CUSTOMER) < est(INVOICE)

est(CUSTOMER) é a mínima tabela estendida que contenha os atributos do For each.

Tabela base: CUSTOMER

Para o exemplo apresentado onde queremos uma lista dos clientes: seu identificar, nome e nome de país, observamos os atributos utilizados dentro do For each, e percebemos que eles são os contidos no print block de nome “customer”: CustomerId, CustomerName e CountryName.

Em que tabelas estão estes atributos?

• CustomerId está em 2 tabelas:- CUSTOMER como chave primária (PK).- INVOICE como chave estrangeira (FK).

• CustomerName está somente em CUSTOMER (é um atributo secundário).

• CountryName está somente em COUNTRY (é um atributo secundário).

GeneXus conhece as relações entre as tabelas. Podemos ver o diagrama correspondente às tabelas nas quais aparecem os atributos do For each (Tools/Diagrams).

Aqui podemos ver porque do requerimento da tabela estendida seja a mínima (entendendo por mínima aquela que envolve um número menor de tabelas). A tabela estendida de INVOICE também contêm todos os atributos do For each, mas não é mínima, pois a de CUSTOMER também os contêm.

Portanto, se vamos percorrer seqüencialmente à tabela CUSTOMER, e para cada registro dessa tabela, vamos acessar a tabela COUNTRY, e recuperar o registro da mesma que cumpre: COUNTRY.CountryId = CUSTOMER.CountryId e para o mesmo recupera-se o valor do atributo CountryName, para poder imprimi-lo, junto com o código e nome do cliente.

Page 168: 93909254 GENEXUS Heuristica Apostila Teorica

168

Listagem de navegação

tabela base

tabela base: a navegada

Acessa para recuperar inforelacionada (CountryName)

A consulta é ordenadapela PK da tabela base

Listagem de navegação

GeneXus oferece para todos os objetos uma lista conhecida como listagem de navegação, que é o resultado da especificação do objeto. Esta listagem é muito útil para os relatórios, já que indica quais são as tabelas que são acessadas em cada For each do Source, se existe um índice para recuperar os dados da tabela base, e em caso de que assim seja qual é esse índice (seu nome), se aplicam filtros sobre os dados ou se devemos listar todos, etc.

Desta maneira, o analista não tem que executar o objeto para verificar se a lógica é a esperada. Estudando a listagem de navegação já têm a informação necessária para saber se está percorrendo a tabela esperada, se estão aplicando corretamente os filtros desejados, etc.

Como pode ser visto, esta listagem mostra para o comando For each que aparece no Source, qual éa tabela base do mesmo, por que ordem essa consulta é resolvida (a ordem que os resultados são impressos), se existe um índice que satisfaça essa ordem, qual é seu nome, e aparecem mais duas informações envolvidas: os filtros de navegação e o diagrama de tabelas.

Os filtros da navegação indicam que faixa da tabela base que vai ser percorrida. No Exemplo épercorrida toda a tabela base do For each: começando pelo primeiro registro de CUSTOMER, atéque chegue ao fim de tabela (utilizando o índice ICUSTOMER).

Também é mostrado num pequeno diagrama de tabelas, a tabela base do For each com sua chave primária, e endentadas todas as tabelas da estendida que devam ser acessadas para recuperar a informação associada ao registro da tabela base que está sendo trabalhada em cada interação do For each. Neste caso se mostra somente a tabela COUNTRY.

No comando For each do Exemplo não aparece explicitamente nenhuma informação referente a ordem desejada da impressão da informação do relatório. Neste caso GeneXus escolhe a ordem da chave primária da tabela base do For each. É por esta razão que no For each do Exemplo, GeneXus determinou que a ordem é realizado pelo atributo CustomerId, chave primária da tabela CUSTOMER.

Page 169: 93909254 GENEXUS Heuristica Apostila Teorica

169

For each: cláusulas Where

• Permitem estabelecer filtros sobre os dados que serão recuperados . Exemplo:

• Somente para os registros que cumpram as condições booleanas das cláusulas where são executados os comandos internos ao For each.

• As cláusulas where são aplicadas somente se satisfizer as condições de suas cláusulas when (somente são válidas para arquitetura cliente/servidor).

For eachwhere CustomerName >= &Start when not &Start.IsEmpty()where CustomerName <= &End when not &End.IsEmpty()

print customerEndfor

Para restringir os dados que queremos listar no For each são utilizadas as cláusulas where do comando.

Se na listagem de clientes não queremos listar todos os clientes, mas apenas aqueles cujo nome esteja dentro de uma faixa inserida pelo usuário, então devemos agregar ao For each que havíamos visto uma cláusula where, para especificar os filtros desejados sobre os dados:

For eachwhere (CustomerName >= &Start) and (CustomerName <= &End)

print customerEndfor

onde as variáveis &Start e &End devem ser definidas no procedimento com o mesmo tipo de dados que CustomerName, e as carregar com valores fixos ou recebidos por parâmetro1.

Com a cláusula where definida estamos dizendo ao GeneXus que não queremos todos os registros da tabela base, e sim, somente aqueles que satisfaçam a condição booleana da cláusula.

No exemplo escrevemos uma cláusula somente where com uma condição composta, mas poderíamos ter programando o mesmo com duas cláusulas where, como mostramos no slide acima.

Quando aparecem vários “where” a condição de filtro que vai ser aplicada sobre os dados é a conjunção booleana de todas as Condições dos “where” que apareceram.

Observemos que no slide os comandos where estejam condicionadas com as claúsulas when. Se interpreta da seguinte forma: os filtros estabelecidos pelo where são aplicados somente quando o when é satisfeito. Isto é lido da seguinte forma: o filtro estabelecido será aplicado pelo where somente quando satisfaça a condição do when.

No exemplo, somente é aplicado o primeiro filtro: “CustomerName >= &Start” se a variável &Start não for vazia. Se for vazia, este filtro não será aplicado. Igual é ao caso da segunda cláusula when. Observar que se &Start e &End estejam vazios, não serão aplicados nenhum dos comandos where, e portanto serão listados todos os clientes (como se não existissem os comandos where).

Cada condição booleana de um “where” pode estar composta de várias expressões booleanas concatenadas com os operadores lógicos and, or e not. __________________________________________________________________________________

1 A través de um objeto que é pedido ao usuário, por exemplo um Web Panel.

Page 170: 93909254 GENEXUS Heuristica Apostila Teorica

170

Listagem de navegação

Listagem de navegação

Aparece um novo elemento nesta listagem que não existia, quando não tínhamos cláusulas where: os constraints (restrições).

Que informação ganhamos com esta listagem de navegação?

• que a tabela base do For each continua sendo CUSTOMER

• que a ordem da consulta continua sendo por CustomerId, utilizando o índice ICUSTOMER correspondente

• que continua percorrendo toda a tabela CUSTOMER em busca da informação

• mas para cada cliente avalia se cumpre as restrições que aparecem enumeradas (CustomerName>= &Start se &Start não estiver vazia e CustomerName<=&End se &End não estiver vazio) e somente caso se cumpra, executar para esse cliente os comandos que aparecem dentro do For each. Neste caso, imprime os valores dos atributos do Printblock “customer”: CustomerId, CustomerName, CountryName.

• que deve acessar a tabela COUNTRY cuja chave primária é CountryId para obter algum dado (CountryName)

Page 171: 93909254 GENEXUS Heuristica Apostila Teorica

171

For each: cláusulas Where

• Atributos permitidos: os atributos da tabela estendida da tabelabase do For each

Exemplo:

For eachwhere CountryName = ‘Uruguay’

print customerEndfor

Os atributos utilizados nas condições de filtro podem ser de qualquer tabela estendida do For each.

No exemplo, a tabela base do For each é CUSTOMER, estamos filtrando os dados a serem recuperados utilizando o atributo CountryName, que é da tabela COUNTRY, pertencente à tabela estendida de CUSTOMER.

Neste exemplo nada foi feito em relação à ordem, os dados aparecerão ordenados pela chave primária da tabela base, ou seja, pelo identificador de cliente, CustomerId. .

Page 172: 93909254 GENEXUS Heuristica Apostila Teorica

172

For each: cláusula Order• Permite estabelecer a ordem que os dados serão recuperados.

Exemplos:

• Para determinar que a ordem seja descendente o atributo deve estar entre parênteses. Ex: order (CustomerName)

For each order CustomerNameprint customer

Endfor

For eachorder CustomerName when not (&Start.IsEmpty() and &End.IsEmpty())

print customerEndfor

Se queremos realizar uma lista de todos os clientes, ordenado por nome do cliente ao invés do código, precisamos modificar o comando For each agregando esta informação da ordem.

Fazemos isso utilizando a cláusula order do For each, como mostramos no primeiro exemplo.

Como não existe um índice definido na tabela CUSTOMER por atributo CustomerName, o GeneXus indicará na listagem de navegação mediante uma advertência (“warning”) que não existe um índice para satisfazer a ordem, o que pode ocasionar problemas de performance, dependendo da plataforma de implementação, da quantidade de registros que devem ser lidos da tabela, etc.

Em ambientes cliente/servidor, se não existe índice para satisfazer a ordem, o For each se traduz numa consulta SQL (“select”) que é resolvida pelo motor do DBMS da plataforma.

Igual o caso dos comandos where, em plataformas cliente/servidor a cláusula order pode ser condicional, como o exemplo dois.Caso a condição when não for cumprida, essa ordem não será utilizada e não existir ordem incondicional (sem a cláusula when) como no exemplo, a ordem será indefinida, isto é, a ordem poderá variar de DBMS a DBMS e inclusive entre execuções seguidas.

Podem ter várias cláusulas order consecutivas condicionais (com cláusula when) em arquiteturas cliente/servidor e uma sem condição (a última da lista). O primeiro comando order cuja condição do when for satisfeita, será a ordem escolhida para ser utilizada.

Clásula Order None: clásula que evita que GeneXus escolha por default a ordem dos atributos da chave primária da tabela base e utiliza uma ordem de navegação indefinida.Se utilizar a cláusula Order None, GeneXus entende que não deseja estabelecer nenhuma ordem em particular e delega esta tarefa ao DBMS.A cláusula order none pode ter condição (when).

Page 173: 93909254 GENEXUS Heuristica Apostila Teorica

173

Listagem de navegação

For each order CustomerNameprint customer

Endfor

Listagem de navegação

Quando não existe um índice que satisfaça o ordem de um For each, como é o caso do Exemplo, o analista GeneXus pode resolver criá-lo (índice de usuário). Na maioria dos casos o relatório serámais eficiente desta maneira, mas o índice é mantido (implicando num maior armazenamento e maior processamento para que o índice seja mantido atualizado)

Não é possível recomendar a priori qual das duas soluções é a melhor (índice temporário vs índice de usuário), portanto deve-se estudar, caso por caso, a solução particular levando em consideração a plataforma de implementação e sendo fundamental a analisar a freqüência que o relatório éexecutado. De qualquer maneira, se no início não foi definido o índice de usuário e posteriormente decide-se fazê-lo, somente é preciso que o relatório seja gerado novamente (sem modificar nada do que foi programado) e o relatório passará a utilizá-lo.

A listagem de navegação anterior mostra o seguinte:

• a tabela base do For each é CUSTOMER• a ordem é por CustomerName

• não existe um índice definido para esse atributo• toda a tabela CUSTOMER com a ordem especificada será recorrida• não tem condições de filtro, todos os registros da tabela executarão os comandos dentro do For each (neste caso, o comando print)

Page 174: 93909254 GENEXUS Heuristica Apostila Teorica

174

Se queremos filtrar os clientes por determinada faixa de nomes, o primeiro exemplo, como não foi especificada a cláusula order, GeneXus ordena pela chave primária, ou seja, CustomerId.

Neste caso, a listagem de navegação mostra que deve-se percorrer toda a tabela CUSTOMER, e para cada registro da mesma deve-se analisar se o registro cumpre ou não as condições (restrições ou “constraints”). Em caso afirmativo, será impresso o mesmo os dados correspondentes.

Ao invés de ordenar os dados por CustomerId vamos fazer uma ordenação por CustomerName, como no segundo exemplo, a tabela base é percorrida ordenada por CustomerName e como nos filtros estabelecemos que queremos somente aqueles clientes cujo nome, CustomerName, esteja na faixa determinada, já não sendo necessário recorrer toda a tabela base para obter os dados que cumprem com as Condições!

A segunda consulta está otimizada nesse sentido. Prestar atenção que o GeneXus não criou um índice por CustomerName de forma automática, e aqui temos que avaliar se é conveniente criar um índice de usuário (será mantido pelo GeneXus depois de criado) ou não criar o índice e deixar que seja criado um índice temporário em execução para resolver a consulta se o DBMS não pode fazer de outra forma.

A listagem de navegação mostra se a consulta está ou não otimizada, de acordo se toda a tabela épercorrida (desde “First Record” até “End of table”) ou apenas uma faixa mais reduzida

OTIMIZAÇÃO: Ordem compatívelcom os filtros

For each order CustomerNamewhere CustomerName >= &Startwhere CustomerName <= &End

print customerEndfor

For eachwhere CustomerName >= &Startwhere CustomerName <= &End

print customerEndfor

Não se percorre todaa tabela base:otimizado!

Toda a tabela base é percorrida.

Page 175: 93909254 GENEXUS Heuristica Apostila Teorica

175

A listagem de navegação nos informa que a consulta está otimizada já que percorre somente os registros incluídos no filtro (desde CustomerName>=&Start até CustomerName <=&End).

Para determinar a ordem levar em consideração:

• Os atributos da cláusula Order especificada pelo usuário • As restrições que aplicam ao nível (atributos mencionados na regra Parm do procedimento, condições explícitas tanto no Where como nas Conditions) • A existência de índices sobre estes atributos.

Distinguimos 2 casos:

1) Se escreve uma cláusula order

•O For each fica ordenado por esses atributos, exista ou não um índice por estes. •Se não existe um índice com os atributos do order, mas existem condições implícitas ou condições explícitas por igualdade, se busca se existe um índice que contenha os atributos das condições mais os do Order. A condição explícita prevalece sobre a implícita para a determinação do Order, em caso que sejam diferentes e exista índice por cada uma delas. •Se existe um índice, os atributos das condições serão agregadas na lista do Order para que dito índice seja considerado em seu lugar.

2) Não se escreve cláusula order

•Neste caso, se existe algum índice para os atributos da condição, o Order fica determinado pelos atributos do índice.•Se não existe um índice que corresponda com as condições, ou seja que não se pode otimizar a percorrida segundo as condições do nível, então se ordena pelos atributos da Primary Key.

OTIMIZAÇÃO: Ordem compatívelcom os filtros

GeneXus sempre tenta encontrar a melhor ordem para que a consulta seja otimizável, isto é, coincida com algum índice definido na base de dados.

Page 176: 93909254 GENEXUS Heuristica Apostila Teorica

176

Por exemplo, se temos as transações:

COUNTRY CITY{ {

CountryId* CountryId*} CityId*

}

O For each:

For Each order CityIdWhere CountryId = 1

...Endfor

Percorre a tabela CITY, ordenando por: CountryId, CityId e utilizando o índice ICITY (índice por chave primária que contem ambos atributos).

Ainda é o próprio DBMS que resolve o plano de acesso mais apropriado, a informação antes mencionada influirá em sua determinação.

Page 177: 93909254 GENEXUS Heuristica Apostila Teorica

177

For each: cláusula Defined by

• Não oferece funcionalidade alguma referente aos dados a serem recuperados.

• Utilizada exclusivamente para ter um elemento a mais para a determinação da tabela base do For each desejado.

For eachdefined by InvoiceDate

print customerEndfor

Exemplo: Mín. estendida que contenha InvoiceDate, CustomerId, CustomerName, CountryName:

est(INVOICE) � tabela base INVOICE

Pode ocorrer de que um For each tenha mais de uma tabela base cuja estendida contenha os atributos do For each, sendo mínima. Frente esta ambigüidade, GeneXus escolhe a “primeira” destas tabelas estendidas mínimas.

Para resolver este tipo de ambigüidade surge a cláusula defined by, que permite usar atributos da tabela base desejada, que não serão utilizados para devolver a consulta ordenada por esses atributos, nem para filtrar informação, nem para ser mostrados no relatório (não tem nenhuma funcionalidade com respeito aos dados àrecuperar), apenas para aportar mais informação que permita determinar a tabela base do for each.

Na cláusula Defined by devemos fazer referência pelo menos à um atributo da tabela base desejada.

Da mesma forma, pode ser utilizada para modificar qual é a tabela base em caso de não utilizar nenhum atributo mais dentro do For each. Este é o caso do exemplo apresentado, não que não queremos listar todos os clientes da tabela CUSTOMER, pelo contrário, queremos listar todos os clientes das faturas. Se não utilizar nenhum atributo dentro do For each de INVOICE , a tabela base é a de CUSTOMER.

Na maioria dos casos não é necessário utilizar este comando. Para procedimentos mais ou menos complexos, quando não exista problema de ambigüidade, recomenda-se o uso do Defined by pois melhora bastante o tempo de especificação do procedimento. Contudo, não é aconselhável seu uso indiscriminado. A desvantagem de utilizar esta cláusula quando não énecessário é que “ata” um pouco mais o código ao desenho das tabelas.

Por exemplo, não foi criada uma tabela COUNTRY, e para cada cliente o país que ele pertence, como atributo secundário. Se quisermos uma listagem dos clientes e seu país, seriam equivalentes:

For each For eachDefined by CountryName

print customer print customerEndfor Endfor

onde customer é um Printblock com os atributos CustomerId, CustomerName e CountryName.Se agora decidir criar a tabela COUNTRY e ter na transação “Customer” a CountryId como FK, o primeiro For each continuará sendo válido e fazendo o que queremos, o segundo deixará de funcionar, ja que no Defined By não tem nenhum atributo da tabela base.

Page 178: 93909254 GENEXUS Heuristica Apostila Teorica

178

• Atributos permitidos: podem aparecer vários atributos da tabela estendida, mas pelo menos um deve corresponder a tabela base desejada (caso contrário ocorre um erro).

• Sugere-se que seja utilizado atributos secundários, visto que os mesmos estão em uma única tabela do modelo e isto evita ambigüidades.

For each: cláusula Defined by

Podem aparecer vários atributos, no caso de um único atributo não determinar a tabela base, onde ao menos um deles deverá estar associado à tabela base desejada.

Recomenda o uso do defined by de atributos secundários da tabela base que desejamos navegar, já que os atributos secundários somente podem estar em uma tabela do modelo e desta forma eliminamos por completo toda possível ambigüidade.

Isto não é obrigatório, podemos usar no Defined by para atributos primários quando notarmos que não haverá ambigüidade na eleição da tabela base.

Um erro comum é acreditar que quando um For each tem esta cláusula, a tabela base do mesmo fica determinada exclusivamente a partir dos atributos mencionados no defined by.

A realidade é que os atributos do defined by determinam uma ou mais tabelas base candidatas a serem a tabela base do For each, mas tendo selecionado a tabela base candidata, sua estendida contêm todos os demais atributos do For each, além dos do defined by.

Se nenhuma das possíveis tabelas base candidatas cumprem esta condição, então o relatório daráum erro ao ser especificado, e não poderá ser gerado (recordemos que todos os atributos do For each devem estar contidos em uma mesma tabela estendida).

Page 179: 93909254 GENEXUS Heuristica Apostila Teorica

179

For each: cláusula When none

• Permite executar determinado código quando não encontrar nenhum registro no For each que cumpra as condições.

• Exemplo:

For eachwhere CustomerName >= &Startwhere CustomerName <= &End

print customerWhen none

print messageEndfor

O Printblock menssage (poderá ter um texto advertindo ao usuário que não existam clientes que cumpram os filtros) executa somente quando não entrar no For each, isto é, quando não tem nenhum registro correspondente na tabela base do For each para que se cumpram as Condições de filtro

Também aplica-se o For each [selected] line, XFor Each y XFor First, comandos que veremos mais adiante.

A cláusula when none deve ser a última dentro do For each. As ações a serem realizadas quando não existe nenhum registro que cumpra as condições, ficam determinadas pelo bloque de código que tem dentro cláusula when none do For each e do endfor.

Quando um For each não tem condições de filtro, os comandos do When none serão executados somente no caso em que a tabela base do For each esteja vazia, porque somente nesse caso não haverá nenhum registro que cumpra as condições de filtro.

Importante:

•Se aparecer atributos no bloque de código correspondente ao When none, estes não são levados em consideração para determinar a tabela base do For each.

• Se incluir For eachs dentro do When none não se inferem Joins nem filtros de nenhum tipo com respeito ao For each que contêm o When none, já que são considerados dos For eachs paralelos.

Page 180: 93909254 GENEXUS Heuristica Apostila Teorica

180

Comando For each - Sintaxe

For each[{[order] order_attributesi [when condi]}... | [order none] [when

condx]][using DataSelectorName([[parm1 [,parm2 [, ...] ])][{where {conditioni when condi} |{attribute IN DataSelectorName([[parm1 [,parm2 [, ...] ]} }...]

[defined by defined_attributes][Blocking NumericExpression]

code1[when duplicate

code2][When none

code3]Endfor

A Sintaxe apresentada generaliza o exemplo com o que estamos trabalhando.

Order order_attributes::= att1, …, attn É uma lista de atributos, que indica a ordem da consulta, sendo atti um atributo da base de conhecimento escrito simples, ou entre parênteses. Quando um atributo do order aparece entre parênteses está indicando a ordem descendente para o mesmo.

Podem se mencionar atributos da tabela estendida.

É possível definir várias cláusulas order condicionais, e uma incondicional, que deveria ser a última listada. Respondendo ao fato de que somente uma dessas cláusulas order tomará efeito, se vão avaliando suas condições (as do when) até a primeira que de True, e com essa fica. Se nenhuma der true e existe uma cláusula incondicional (isto é, sem when), pega essa ordem. Se não existe tal cláusula, ou ordem será indefinido, querendo isto significa que dependerá da plataforma, e incluso poderá variar entre execuções sucessivas. A justificatova para escrever cláusulas order condicionais, deriva se quisermos aplicar cláusulas where condicionais. Isto é, por motivos de otimização das consultas.

Por exemplo, se queremos filtrar por CustomerName > &Name when not &Name.IsEmpty(), então para otimizar a consulta deveríamos ordenar por CustomerName, mas se não aplicar o filtro, visto que &Name está vazio, então será melhor deixar uma ordem indefinida.Para isso especificamos a cláusula order condicional:

order CustomerName when not &Name.IsEmpty()

Ao invés do exemplo anterior, também pode ser especificado uma cláusula order none que éutilizada quando não nos interessa uma ordem em particular e queremos que fique indefinido.

Page 181: 93909254 GENEXUS Heuristica Apostila Teorica

181

Escolha do índice: GeneXus escolhe automaticamente o índice que utilizará para satisfazer a ordem. GeneXus sempre tentaráencontrar a melhor ordem possível para que a consulta seja otimizável, isto é, coincida com algum índice definido na base de dados. Para determinar a ordem é levado em consideração:

•Os atributos da cláusula Order especificada pelo usuário •As restrições que aplicam ao nível (atributos mencionados na regra Parm do procedimento, condições explícitas tanto no Where como nas Conditions) •A existência de índices sobre estes atributos.

Ainda é o próprio DBMS que resolve o plano de acesso mais apropriado, a informação antes mencionada influirá em sua determinação.

Os atributos do order são levados em consideração na hora de determinar a tabela base do For each. Mas eles por si só não determinam. Devem examinar-se também outras partes do For each.

Using DataSelectorNamePermite definir filtros de acordo ao critério definido no DataSelector1 definido em DataSelectorName.

Where ConditionCondição booleana que deverão cumprir os dados para ser processados dentro do For each, podendo ser uma condição composta, utilizando os operadores lógicos and, or e not.

Os atributos que apareçam na condição booleana podem ser tanto da tabela base do For each como da estendida.

Como se desprende da sintaxe, para um mesmo For each podem especificar-se n cláusulas where sucessivas, cada uma com uma condição:where cond1where cond2...where condn

A ocorrência de n cláusulas where é equivalente a ocorrência de uma única cláusula, com a conjunção booleana das condições:

where cond1 and cond2 and … and condn

Os dados da tabela estendida do For each que cumpram com todas as condições dos “where” serão os processados nos comandos internos ao For each (os do bloque de código code1).

Da mesma forma que ocorre com a cláusula order, pode condicionar os filtros (com cláusulas when). Desta maneira, primeiro se avalia a cláusula when de cada cláusula where, e caso a condição seja cumprida, aplicam o filtro especificado no where.

Para que uma restrição condicional possa ser gerada como tal, a condição do when tem que ser “avaliável" pelo DBMS que se está utilizando, isto é, GeneXus tem que saber como escrever a condição na linguagem própria do DBMS utilizado.

Se não puder gerar como tal (porque o gerador não o suporta ou porque a condição não pode ser escrita na linguagem do DBMS) se transformará em um filtro "comum" substituindo o WHEN por um OR. Além disso, se gerar a mensagem de código spc0053 –‘Unsupported conditional constraint”%1” changed to standard constraint %2.’ - no Diagrama de Navegação.

Nota: Existe também a cláusula Option Distinct do For Each que permite retornar os registros que cumpram unicidade de valores dos atributos referenciados. Não veremos esta cláusula. O leitor interessado pode recorrer as distintas fontes de documentação para estudá-la (Help, Wiki, Release Notes, etc.)

Defined bydefined_attributes::= att1, att2,…,attpÉ um conjunto de atributos que serão utilizados somente efeitos de determinar a tabela base do For each.

Ao mencionar aqui alguns atributos da tabela que se deseja percorrer, estes participarão na determinação da tabela base do For each.

A cláusula defined by aparece para solucionar alguns problemas de ambigüidade na determinação da tabela base (quando existem várias tabelas estendidas mínimas que contenham os atributos do For each) ou quando se deseja que a tabela base seja outra, diferente da que seria determinada pelos atributos que aparecem no resto do For each (este caso tem sentido quando se estude “controle de corte”). Também se utiliza para melhorar o tempo de especificação em procedimentos complexos.

Os atributos desta cláusula não determinam por si só a tabela base do For each. Poderia acontecer que estes atributos determinam tabela como a candidata a tabela base, mas se depois os outros atributos do For each não estão contido na estendida dessa tabela, o For each dará um error e o objeto que o contem não poderá ser gerado.

code1É uma sucessão de comandos que podem utilizar atributos da tabela estendida do For each. A este bloque de código o chamaremos corpo do For each.

Os atributos que figurem neste bloque de código participam na determinação da tabela base do For each.

______________________________________________________________________________________________

1 O objeto DataSelector será visto mais adiante no curso.

Page 182: 93909254 GENEXUS Heuristica Apostila Teorica

182

Os comandos especificados serão executados seqüencialmente para os dados da tabela estendida que cumpram as Condições de filtro, considerando os dados na ordem especificado.

BlockingEste tema será abordado mais adiante do curso, mas a idéia geral é que a especificação desta clásula permite realizar atualizações e eliminações em blocos, reduzindo assim o número de acesso a base de dados.

When DuplicateEsta cláusula tem sentido somente em procedimentos (já que trata de atualização) e será visto mais adiante.Esta cláusula é executada se dentro do corpo do For each code1, atualizar um atributo que é chave candidata (possui índice único) e já existir um registro com esse valor. GeneXus utiliza o índice único para assegurar a unicidade dessa chave candidata e caso encontre duplicação, se o For each tem essa cláusula programada, executará seu código: code2.Não existindo a cláusula nenhum código será executado.

When noneEm caso de que não existam dados que cumpram as Condições de filtro não será executado os comandos do code1 e sim os bloque de código code3.

� Tanto para When Duplicate como para When none: incluindo um comando For each dentro dentro de um dos dois, não são inferidos nem joins nem filtros com respeito ao For each que o contêm (when none|when duplicate). São considerados navegações independentes (code1, code2 e code

3).

Page 183: 93909254 GENEXUS Heuristica Apostila Teorica

183

Comando For each• Podemos fazer que o GeneXus escreva o código do For each,

inserindo “snippets” (menu Insert ou a partir do Toolbox):

Os “code snippets” são moldes de código que GeneXus tem predefinido, que nos ajudam a escrever o código fonte. Quando estamos trabalhando no Source de um procedimento, a Toolbox nos mostra vários snippets que nos facilitam a escrita do comando For each.

Os snippets possui por sua vez um “atalho” (shorcut), que fazem que a escrita do código seja mais rápida todavia. Por exemplo, digitando simplesmente “fe” se escreve automaticamente o seguinte código:

For each/*For each Code*/

Endfor

Depois o usuário substitui a linha de comentários com o código necessário.

A lista dos atalhos de cada snippet, é a seguinte:

• fe (For each)• feu (For each using)• fen (For each When none)• feun (For each using When none)• few (For each where)• feuw (For each using where)• fewn (For each where When none)• feuwn (For each using where When none)

Page 184: 93909254 GENEXUS Heuristica Apostila Teorica

184

For eachs paralelos

• Chamamos assim os casos dos For eachs que estão escritos de forma sequencial (não aninhada) . Exemplo:

• Também é utilizado quando um For each aparece dentro da cláusula When none ou when duplicate de outro.

• As navegações são totalmente independentes

For eachprint invoice

EndforFor each

print billEndfor

O For each é um comando como outros, e portanto pode aparecer várias vezes dentro do Source, tanto em forma paralela (independente), como aninhado a outro For each.

Quando dentro do corpo do For each (code1) aparece outro For each, dizemos que trata-se de For eachs aninhados. GeneXus suporta vários níveis de aninhamento para os For eachs.

Se um For each aparece no bloque de código code3, pode ser visto como For eachs aninhados porque um aparece dentro de outro, muda o comportamento, é igual a ter For eachs paralelos.

Um For each “aninhado no when none” de outro, somente é executado se não tem nenhum registro da tabela base do For each que o contêm que cumpra as condições de filtro.

No exemplo, “invoices” e “bill” são dois Printblocks do Layout que contêm os atributos das tabelas INVOICE e BILL (recibo) respectivamente.

Temos definido dois For eachs paralelos. O primeiro percorre todas as faturas e o segundo todos os recibos.

Page 185: 93909254 GENEXUS Heuristica Apostila Teorica

185

For eachs aninhados

• Para cada registro do For each principal se busca recuperar muitos registros do aninhado

For each...For each

...Endfor...

When none...

Endfor

Corpo do For each principal

O For each é uma estrutura repetitiva, que permite recuperar muitos registros de uma tabela. Quando pensamos em For eachs aninhados, é evidente que o que buscamos recuperar é, para cada registro do principal, muitos registros do aninhado.

O que o GeneXus detecta que se quer fazer com este tipo de estruturas, de forma de inferir o comportamento automaticamente com o menor codificação possível?

• para cada registro de uma tabela recuperar alguns de outra: os relacionados.• para cada registro de uma tabela recuperar todos de outra. • processar informação por grupos, isto é, agrupar os registros de uma tabela segundo o valor de um atributo ou conjunto de atributos e para cada grupo, recuperar alguns registros: os correspondentes ao grupo.

Sempre a relação é um a muitos: para cada registro de uma tabela recuperar muitos da outra (podendo-se tratar da mesma tabela).

Utilizando esta lógica é que o GeneXus infere as tabelas base e o comportamento dos For eachs aninhados, sabendo que o que desejamos é implementar alguma das três opções anteriores.

Por exemplo, se queremos elaborar uma lista de todas as faturas do sistema, sendo que imprimiremos detalhe de cada uma, devemos navegar por duas tabelas: INVOICE (que armazena os cabeçalhos) e INVOICEDETAIL (que armazena as linhas), e o faremos de uma forma bem simples, sem colocar o nome das tabelas, e sem que explicar tudo, como veremos.

Outro Exemplo é de uma lista de todos os clientes, onde para cada um se quer imprimir, além de seus dados pessoais, os dados de todas suas faturas. Este comportamento se dá com um par de For eachs aninhados, onde o primeiro navega pela tabela CUSTOMER e o segundo navega pela tabela INVOICE, recuperando somente as faturas desse cliente, como veremos em seguida.

Page 186: 93909254 GENEXUS Heuristica Apostila Teorica

186

For eachs aninhados

• Exemplo: imprimir todas as faturas com suas respectivas linhas

For eachprint invoice_headerFor each

print invoice_linesEndforprint invoice_total

Endfor

{InvoiceId, InvoiceDate, CustomerName}

{ProductDescription, ProductPrice, InvoiceLineQuantity, InvoiceLineAmount}

{InvoiceTotal}

Se queremos realizar uma lista de todas as faturas do sistema, onde para cada uma se mostre tanto a informação do cabeçalho como das linhas.

No Source programado, percorremos à tabela INVOICE, imprimindo os atributos que nos interessam do cabeçalho e para cada registro dessa tabela, percorremos a tabela INVOICEDETAIL, para imprimir os atributos que nos interessam de suas linhas.

Podemos perceber o quão simples é esse processo, simplesmente utilizando os atributos que queremos usar, ficando o GeneXus encarregado do resto.

Observemos que nem sequer tivemos que especificar a condição de filtro sobre os registros de INVOICEDETAIL a recuperar. O GeneXus se dá conta da relação existente entre as tabelas, e aplica automaticamente a condição de filtro sobre os dados, de maneira que só sejam impressas as linhas “dessa” fatura (lembrar que algo idêntico acontece com as fórmulas verticais, como InvoiceTotal, onde a condição de filtro sobre os registros a serem somados ou contados ficava implícita, e não precisa que especificá-la).

Page 187: 93909254 GENEXUS Heuristica Apostila Teorica

187

For eachs aninhados

• Exemplo: imprimir todas as faturas com suas respectivas linhas

INVOICE INVOICEDETAIL

Para cada registro de INVOICE imprimir alguns de seus dados (InvoiceId, InvoiceDate) e de sua estendida (CustomerName).

Depois navega por INVOICEDETAIL e recupera os registros que correspondam a fatura que se está imprimindo.

Os que cumpram a condição implícita:INVOICEDETAIL.InvoiceId = INVOICE.InvoiceId

Como para um For each simples, o GeneXus deve determinar para cada For each (principal e aninhado) qual é sua tabela base. E a partir dessa determinação, utilizará a lógica correspondente.

Mais adiante veremos com exatidão como é que o GeneXus determina cada tabela base. Aqui ficaremos com idéia intuitiva de que o faz de forma similar como o fazia no caso de um For each simples.

Encontra, pois, que deve percorrer as tabelas INVOICE e INVOICEDETAIL.

Como essas tabelas estão relacionadas de acordo a uma relação 1-N infere mais que isso: infere também na aplicação da condição sobre os dados de INVOICEDETAIL que indicamos acima.

Page 188: 93909254 GENEXUS Heuristica Apostila Teorica

188

For eachs aninhados

• GeneXus deve:

• Determinar a tabela base de cada For each.

• A partir disso se define as navegações que realizará para cada For each (existem 3 casos possíveis).

• A lógica dos For eachs dependerá das relações encontradas entre as tabelas determinadas.

Quando temos dois For eachs aninhados,GeneXus deve determinar a tabela base de cada um, e essas serão as tabelas que se navegarão.

Para cada registro da tabela base do For each principal, serão executados os comandos do corpo do mesmo. Entre esses comandos, encontra-se o For each interno, que será executado, como qualquer outro comando, no lugar onde estiver realizando uma navegação sobre sua tabela base.

Para a determinação da tabela base do For each aninhado, influencia a tabela base do For each principal, mas as determinações não são por completo independentes, como se pode pensar equivocadamente.

A partir da determinação das tabelas base de cada For each e das relações que encontre o GeneXus entre as tabelas envolvidas, surgem três possíveis casos de For eachs aninhados, que correspondem aos casos enunciados anteriormente: join, Produto cartesiano e corte de controle, respectivamente.

Estudaremos cada um desses casos com exemplos.

Page 189: 93909254 GENEXUS Heuristica Apostila Teorica

189

For eachs aninhados: determinação das tabelas base

Acontece de forma ordenada, determinandocada vez a tabela base de um nível de encadeamento,de fora para dentro: primeiro sedetermina a tabela base do For each mais externo, depois do aninhado a este e assim sucessivamente.

Para cada For each, intervêm unicamenteos atributos do próprio For each: doorder, where, defined by e todos do corpo que não pertençam a um For each aninhado (tampouco intervêm os da cláusula When none).

For each...For each

...Endfor...

When none...

Endfor

Consideremos o caso mais simples, de um par de For eachs aninhados.

• A determinação da tabela base do For each principal, é análoga ao caso de For each simples (sem aninhamentos). Neste caso consideram-se todos os atributos do For each principal, descartando os For eachs aninhados que este contenha (e todos seus atributos). GeneXus encontra a mínima tabela estendida que os contenha e define assim a tabela base através da qual chega a todas as outras.

• Para determinar da tabela base do for each aninhado, GeneXus fixa os atributos utilizados dentro do corpo do mesmo, onde estão incluídos ou dentro da tabela estendida previamente determinada (a do For each principal). Em caso afirmativo, GeneXus determina que a tabela base do For each aninhado será a mesma que a do For each principal. Em caso contrário, busca-se a mínima tabela estendida que cumpra e contenha todos os atributos do For each aninhado e que tenha alguma relação com a tabela base do For each principal. A tabela base de dita tabela estendida, será a tabela base do For each.

Se não puder encontrar uma tabela estendida mínima que cumpra ambas condições, mas cumpre que contenha os atributos, finalmente a escolhe, mas sempre busca a forma de encontrar relações entre ambas tabelas bases. Somente neste último caso de não se encontrar relações, se procede a determinar a tabela base como se fosse For eachs independentes.

Estudaremos um esquema resumindo o anterior depois.

Page 190: 93909254 GENEXUS Heuristica Apostila Teorica

190

For eachs aninhados: determinação das tabelas base

For eachprint invoice_headerFor each

print invoice_linesEndforprint invoice_total

Endfor

{InvoiceId, InvoiceDate, CustomerName}

{InvoiceTotal}

Tabela base For each externo

For eachprint invoice_headerFor each

print invoice_linesEndforprint invoice_total

Endfor

{ProductDescription, ProductPrice, InvoiceLineQuantity, InvoiceLineAmount}

Tabela base For each interno

INVOICE

INVOICEDETAIL

Para o exemplo apresentado anteriormente, mostramos acima como se determina cada tabela base.

Para a do aninhado, como os atributos que figuram não estejam contidos na tabela estendida de INVOICE (que é a tabela base do principal), então se passa a determinar sua tabela base como se explicou anteriormente: se busca a tabela estendida mínima que contenha a ProductDescription, ProductPrice, InvoiceLineQuantity e InvoiceLineAmount, e caso possível esteja reacionada com INVOICE.

A tabela que cumpre ambos requisitos em INVOICEDETAIL.

Page 191: 93909254 GENEXUS Heuristica Apostila Teorica

191

• Tabelas base distintas

• Tabelas base iguais• Controle de Corte: Corresponde ao caso para recuperar informação por

grupos.

Join: se recuperam alguns registros do aninhado, os relacionados.

Produto cartesiano: se recuperam todos os registros do aninhado.

For eachs aninhados: lógica associada

(Caso 1)

(Caso 2)

(Caso 3)

Fe externo

Fe aninhado?

Existe relação implícita que vincule o For each externo com um número N de registros do For each aninhado?

Sim

Não

1

N

Da determinação das tabelas base, surgem os três casos de For eachs aninhados que foram mencionados e que estudaremos um a um em seguida.

Este tema é de vital importância, já que a maioria das aplicações requerem navegações complexas sobre as tabelas, onde se requer uma mistura de todos estes casos.

Page 192: 93909254 GENEXUS Heuristica Apostila Teorica

192

Caso 1: Join

• Distintas tabelas base mas existe uma relação 1-N direta ou indireta entre elas

• Exemplo: Listagem de todos os clientes e suas faturas

For eachprint customerFor each

print invoiceEndfor

Endfor

{CustomerId, CustomerName}

{InvoiceId, InvoiceDate,InvoiceTotal} INVOICE

CUSTOMER

CustomerId

No For each aninhado é ordenado pelo atributo relação: CustomerId

est(principal) ∩∩∩∩ base(aninhado) = {CustomerId}

Este é o caso em que o GeneXus determina que as tabelas base de cada For each são distintas e tem uma espécie de relação 1-N (podendo ser esta indireta) entre as tabelas que se percorre

Ou seja, para cada registro da tabela base do For each principal, GeneXus encontra que tem N relacionados com ele, direta ou indiretamente, na tabela base do For each aninhado.

Ao encontrar esta relação, aplicará condições de filtro automáticas no For each aninhado, de forma a ficar somente com esses registros relacionados.

O exemplo do procedimento que imprime todas as faturas do sistema, com seus detalhes, cai dentro desta categoria. Nesse caso tem uma relação 1-N direta entre as tabelas que se percorre: para cada cabeçalho da fatura, lista-se o mesmo, junto com todas suas linhas da fatura, ou seja, todos os registros de INVOICEDETAIL que estão relacionados com o registro de INVOICE que se estáposicionado em cada interação.

Este é um dos casos mais comuns de For eachs aninhados, onde se quer percorrer uma tabela, e para cada registro da mesma, percorrer outra tabela, relacionada com a primeira por uma relação N-1. O GeneXus encontra nesta relação, e na navegação interna, somente recupera os registros associados, e aí o nome “join” para este caso.

No exemplo apresentado acima ocorre o mesmo. A tabela base do primeiro For each é CUSTOMER, e a do segundo, INVOICE. Como encontra atributo em comum entre a tabela estendida do For each principal e a tabela base do aninhado1, CustomerId, determina que esse atributo atue como condição de filtro na percorrida da tabela do For each aninhado.

------------------------------------------------------------------------------------------------------------

1 Esta é uma forma de expressar formalmente o que havíamos dito em términos informais: relação direta ou indireta 1-N entre as tabelas base. A relação será direta quando a tabela base do principal tenha relação 1-N com a tabela base do aninhado, isto é, seja superordinada desta última. A relação será indireta quando isto não exista uma relação direta entre as tabelas base, mas sim entre a tabela estendida do primeiro e a tabela base do segundo. Também será indireta quando a tabela estendida do aninhado inclua a tabela base do principal. Veremos exemplos em seguida.

Page 193: 93909254 GENEXUS Heuristica Apostila Teorica

193

Caso 1: Join

Vejamos, como o GeneXus faz para determinar as tabelas base. Os atributos utilizados no For each externo são CustomerId e CustomerName, e a tabela base deste For each será CUSTOMER. Observemos que somente participam na determinação desta tabela base os atributos do For each principal, não os do aninhado.

Depois, GeneXus deve encontrar a tabela base do For each aninhado. Os atributos que participam são InvoiceId, InvoiceDate e InvoiceTotal, ou seja, os atributos internos a este For each. Observemos que estes atributos não pertencem a tabela estendida do principal, que era CUSTOMER. Portanto passa a determinar sua tabela base como a de qualquer For each simples: a tabela estendida INVOICE contem todos os atributos do For each aninhado, e é a mínima tabela estendida que os contenha. Portanto, INVOICE será escolhida como tabela base do segundo For each.

Observemos, novamente, que não explicitamos cláusula where no For each aninhado para filtrar as faturas do cliente do For each principal. Justamente, por tratar-se de tabelas relacionadas por uma relação 1-N direta, esta condição é aplicada implicitamente pelo GeneXus e pode ser visto na listagem de navegação acima.

Outro fato interessante que pode ser observado nesta lista: no For each aninhado não foi especificado a cláusula order, GeneXus não escolheu a ordem da chave primária da tabela base e sim pelo atributo da relação, CustomerId. Desta maneira, está otimizando automaticamente a consulta.

Esse caso é uma exceção a regra que fala que quando nenhuma cláusula order em um For each éespecificada, GeneXus determina como ordem o atributo da chave primária da tabela base de dito For each.

Page 194: 93909254 GENEXUS Heuristica Apostila Teorica

194

Caso 1: Join• Exemplo: Listagem de todas as faturas por país

For eachprint countryFor each

print invoiceEndfor

Endfor

{CountryId, CountryName}

{InvoiceId, InvoiceDate, InvoiceTotal}

COUNTRY ⊂ est(INVOICE) porque tem uma relação 1-N indireta ���� condição implícita: todas as faturas do país são listadas

base(principal) ⊂ est(aninhado)

INVOICE

CUSTOMER

CustomerId

COUNTRY

CountryId

Se queremos realizar uma listagem das faturas emitidas pelo país, teremos outro caso de For eachs aninhados com distintas tabelas base, onde a informação que queremos listar está relacionada.

Aqui queremos percorrer às tabelas COUNTRY e INVOICE.

Observemos que elas não estão relacionadas diretamente, mas estão de forma indireta. De fato, COUNTRY pertencem à tabela estendida de INVOICE. Portanto, para cada fatura pode-se encontrar somente um país relacionado à mesma.

Este é um caso um pouco mais complexo que o anterior, porque a tabela estendida do For each principal não tem intersecção com a tabela base do aninhado (est(COUNTRY) ∩ INVOICE = φ), mas existe uma relação 1-N indireta, e o GeneXus a encontra.

Neste caso, a tabela base do For each principal está incluída na estendida do aninhado(COUNTRY ⊂ est(INVOICE)), mas tem uma relação 1-N indireta.

Por este motivo, não necessitamos especificar cláusula where no For each interno para filtrar as faturas do país do For each principal.

Isto pode ser visto claramente na listagem de navegação, que mostrará o filtro:“CountryId = CountryId” para o segundo For each, mas desta vez como ‘Constraint’ visto que não pode otimizar a percorrida.

O leitor pode testar este caso em GeneXus e estudar detalhadamente a listagem de navegação resultante.

Page 195: 93909254 GENEXUS Heuristica Apostila Teorica

195

Caso 2: Produto Cartesiano

• Distintas tabelas base, mas não existe relação 1-N direta nem indireta entre as mesmas.

• O resultado obtido é o produto cartesiano de ditas tabelas: para cada registro da tabela base do For each principal, se recuperamtodos os registros da tabela base do aninhado.

est(principal) ∩∩∩∩ base(aninhado) = φ e

base(principal) ⊄ est(aninhado)

Neste caso o GeneXus não encontra uma relação 1-N direta ou indireta entre as tabelas e portanto não aplica filtros implícitos aos registros do For each aninhado, ou seja, realiza um produto cartesiano entre as tabelas.

O caso ocorre quando:• est(For each principal) ∩ base(For each aninhado) = φ e• base(For each principal) ⊄ est(For each aninhado)

Para cada registro da tabela base do For each principal se recorre toda a tabela base do For each aninhado.

Por exemplo, se a tabela base de um For each foi COUNTRY e a do aninhado PRODUCT, evidentemente não existirá relação e haverá um produto cartesiano e se percorre para cada país, todos os produtos.

O programador pode estabelecer filtros sobre os dados a recuperar, mas estes já não serão condições implícitas inferidas pelo GeneXus, mas sim especificadas explicitamente pelo programador..

Page 196: 93909254 GENEXUS Heuristica Apostila Teorica

196

Caso 3: Controle de Corte

• Exemplo: Para cada cliente que possui faturas, listar os clientes e suas faturas.

No exemplo que vimos anteriormente, da listagem de clientes e suas faturas, o que acontece se um cliente não possuir faturas?

Como a tabela base do For each principal é CUSTOMER, o cliente sai impresso antes de saber-se se tem ou não faturas.

Se não desejamos que isto ocorra, isto é, que apareçam listados clientes que não tenham faturas, então a solução é acessar unicamente as faturas, pois se um cliente está nesta tabela, é porque está em uma fatura!.

Mas para poder agrupar as faturas por cliente, de tal forma de poder mostrá-las desse modo, devemos percorrer a tabela INVOICE ordenada por CustomerId. Desta forma processaremos a informação de um cliente, e depois passaremos ao seguinte, para processar sua informação, e assim sucessivamente.

Se imaginamos um ponteiro que se vai mostrando sequencialmente pela tabela INVOICE, podemos escrever o pseudocódigo de nosso procedimento como segue:

1. Para o registro apontado, reter o valor do atributo de corte ou agrupamento, CustomerId.

2. Acessar a tabela CUSTOMER (que está na estendida de INVOICE) para recuperar o CustomerName e imprimi-lo junto com o CustomerId (“print customer”)

3. Enquanto o valor de CustomerId do registro apontado coincida com o valor retido no passo 1 (aqui se processam todas as faturas do cliente)

a. Imprimir InvoiceId, InvoiceDate e InvoiceTotal do registro apontado.(“print invoice”)

b. Avançar o ponteiro ao seguinte registro e voltar ao passo 3.

4. Voltar ao passo 1. (quando se chega a este ponto, é porque se chegou no final da tabela ou mudou o cliente).

Page 197: 93909254 GENEXUS Heuristica Apostila Teorica

197

Caso 3: Controle de Corte• Exemplo: Para cada cliente que possui faturas, listar suas

faturas.

For each order CustomerIddefined by InvoiceDate

print customerFor each

print invoicesEndfor

Endfor

ordem determina o critério de corte

Cada vez que muda o cliente é definido um grupo novo

O “defined by” foi utilizado para que tabela base seja INVOICE e não CUSTOMER e assim implementar um controle de corte e não um join.

Source

Layout

GeneXus oferece uma forma de programar o que foi visto de uma forma simples.

O pseudocódigo visto na página anterior se programa em GeneXus com um par de For eachs aninhados que estão no slide acima.

Comparando este código com o que vimos anteriormente para o caso de join, vemos que existem somente duas diferenças: a cláusula order que aparece neste código, junto com o defined by. Somente com essas mudanças da lista original, mudamos radicalmente o comportamento, neste caso somente serão listados os clientes que possuem faturas.

Neste caso, ambas cláusulas (order e defined by) são indispensáveis para que este relatório funcione como queremos. Se agregamos somente uma delas, o resultado é outro.

Não é em toda programação de controle de corte que deverá ter uma cláusula defined by no For each principal, mas sim uma cláusula order.

A cláusula order é indispensável, porque é ela que especifica por qual atributo ou conjunto de atributos o corte (ou agrupamento) será realizado. Isto é, especifica essa informação comum ao grupo, que será processada uma única vez (dentro do código do For each externo).

A cláusula defined by não é indispensável em todos os casos. Neste caso foi, porque não especificá-la, GeneXus determinaria como tabela base do For each principal CUSTOMER, que não é o que queremos (pois não queremos implementar um join, como foi feito antes, e sim um corte de controle, para ler somente a tabela INVOICE).

Poderíamos ter utilizar outra solução para modificar a tabela base do For each principal: utilizar em vez do defined by o comando print if detail dentro do corpo do primeiro For each (este comando diz ao GeneXus que tome como tabela base do For each, a mesma que determinar para o aninhado).

Page 198: 93909254 GENEXUS Heuristica Apostila Teorica

198

Caso 3: Controle de Corte

Devem ser cumpridas as condições seguintes para implementar o Controle de Corte:

1. For each aninhados

2. Mesma tabela base

3. Quantos For each? Um a mais que a quantidade de cortes

4. Devemos estabelecer na cláusula order de cada For each externo, o atributo ou conjunto de atributos que queremos “cortar” (“agrupar”).

Um controle de corte é fácil de programar e pode ser feito seguindo as considerações anteriores. Na ordem do For each mais extremo, devemos mencionar o “primeiro” atributo de corte, na ordem do segundo For each devemos mencionar o “segundo” atributo de corte e assim sucessivamente. Não éobrigatório mencionar atributo/s na ordem do For each mais interno (em todos os demais For each éassim).

É utilizado quando desejamos trabalhar com a informação de uma tabela, mas agrupada por algum atributo ou conjunto de atributos.

Os controles de cortes podem ser simples, duplos, triplos, etc.

A seguir veremos um exemplo de um controle de corte duplo.

Page 199: 93909254 GENEXUS Heuristica Apostila Teorica

199

Exemplo: Controle de corte duplo

Vamos supor que queremos como antes listar os clientes e suas faturas, mas queremos agrupar as faturas de cada cliente por data. Isto é, queremos mostrar, para cada cliente, para cada data, as faturas existentes.

Exemplo:

Customer: 1 João Silveira

Date: 12/05/05Invoice Total

1 15

Date: 01/01/06Invoice Total

9 353 30

Customer: 3 Maria Silva

Date: 06/06/05Invoice Total

2 20Date: 12/08/05

Invoice Total4 408 15

Date: 02/02/06Invoice Total

7 20

Como agora queremos agrupar por cliente, e dentro desse grupo por data de fatura, necessitamos três For eachs aninhados:

For each order CustomerIddefined by InvoiceDate

print customerFor each order InvoiceDate

print dateFor each

print invoiceEndfor

EndforEndfor

Como exercício, vamos seguir todos os passos que realiza GeneXus para inferir o comportamento do procedimento.

1. Determinação da tabela base de cada For each

Como sempre, para determinar as tabelas base de For eachs aninhados, se começa de fora para dentro, determinando de cada For each, sem levar em consideração os atributos dos For eachs internos ao que se está considerando.

Page 200: 93909254 GENEXUS Heuristica Apostila Teorica

200

2. Determinação da navegação

Depois de determinadas as tabelas base, GeneXus determina a navegação. Como neste caso são três For eachs sobre a mesma tabela base, se trata de um controle de corte duplo.

Podemos pensar que quando falamos de controle de corte, seja simples, duplo, triplo, quádruplo, etc, temos somente um ponteiro utilizado para avançar nos registros da tabela base.

Lembremos que a cláusula order é fundamental para estabelecer o critério de corte em cada par de For eachs.

Como em nosso caso queremos agrupar por CustomerId e depois, para todas as faturas com esse cliente, agrupar por InvoiceDate, então teremos que ordenar o primeiro For each por CustomerId e ou imediatamente aninhado por InvoiceDate.

No exemplo estamos dizendo que:

Enquanto não encontrar o final da tabelaImprimir os dados do cliente da fatura atualEnquanto não mude o cliente

Imprimir a data da fatura atualEnquanto não mude a data

Imprimir os dados da fatura atual (nro e total)Avançar o ponteiro ao seguinte registro

For each order CustomerIddefined by InvoiceDate

print customerFor each order InvoiceDate

print dateFor each

print invoiceEndfor

EndforEndfor

Tabela base 2do. For eachConsideram os atributos dos lugares que estão em negrito e como todos eles estão incluídos na estendida do 1er. For each, então se determina a mesma tabela base: INVOICE

For each order CustomerIddefined by InvoiceDate

print customerFor each order InvoiceDate

print dateFor each

print invoiceEndfor

EndforEndfor

Tabela base 3er. For eachConsideram os atributos dos lugares que estão em negrito e como todos eles estão incluídos na estendida do 2do. For each, então se determina a mesma tabela base: INVOICE

For each order CustomerIddefined by InvoiceDate

print customerFor each order InvoiceDate

print dateFor each

print invoiceEndfor

EndforEndfor

Tabela base 1er. For eachSomente são considerados os atributos dos lugares que estão em negrito.Mínima tabela estendida que os contem: est(INVOICE)

Page 201: 93909254 GENEXUS Heuristica Apostila Teorica

201

Recomendamos programar em GeneXus este procedimento e observar cautelosamente a listagem de navegação.

Verá que GeneXus escolhe uma única ordem, quando não tem um índice criado: o composto pela concatenação das ordens de cada For each com cláusula order. Este resultado é claro se pensarmos que um único ponteiro vai se deslocando pela tabela base.

Uma vez determinado a Order do Controle de Corte se otimiza, buscando o melhor índice levando em consideração as condições explícitas ou implícitas do nível.

Resumo: Determinação geral das tabelas Base

Acontece de forma ordenada, determinando cada vez a tabela base de um nível aninhado, vendo de fora para dentro: primeiro determina-se a tabela base do For each mais externo, depois o que está aninhado a este e assim sucessivamente.

Determinação da Tabela Base do For Each ExternoDetermina a partir dos atributos que aparecem dentro desse For each: cláusulas order, where, defined by e corpo do For each, exceto os atributos que estejam dentro do For each aninhado. Não participam os atributos que estão dentro do When none, no caso do For each principal ter esta cláusula. Como no caso de um For each simples, que se encontra a mínima tabela estendida que contenha ditos atributos.

Determinação da Tabela Base do For Each AninhadoPodemos chegar a pensar por analogia que deveríamos extrair os atributos do For each aninhado, e fazer o mesmo que antes, ou seja, encontrar a mínima tabela estendida que contenha esses atributos, como se fosse um For each independente. Mas não são For eachs independentes!

Para o For each aninhado, o GeneXus verifica se os atributos utilizados dentro do corpo do mesmo estão incluídos ou não dentro da tabela estendida previamente determinada. Em caso afirmativo, o GeneXus determina que a tabela base do For each aninhado será a mesma que a do For each principal ( e será um caso de controle de corte)

Caso contrário, se determina da seguinte maneira: busca a mínima tabela estendida que contenha a todos os atributos do For each aninhado, tratando de encontrar aquela que tenha alguma relação com a tabela base do For each principal.Se não encontra uma tabela estendida que contenha a todos os atributos do For each aninhado e que além desta relacionada, fica com a tabela estendida mínima que contenha os atributos ainda que não tenha relação.

Page 202: 93909254 GENEXUS Heuristica Apostila Teorica

202

Comandos de controle

if condbloque1

[elsebloque2]

endif

do while condbloque

enddo

do casecase cond1

bloque1[case cond2

bloque2]......

[case condn

bloquen]otherwise

bloquen+1endcase

for &var=inicio to fin [step salto]bloque

Endfor

for &var in Expression bloque

Endfor

Os comandos introduzidos são similares aos existentes nas linguagens de Programação imperativa conhecidas, por isso não incluímos a documentação deste tema. Pode ser encontrada no curso não presencial ou no Help do GeneXus. Os dois últimos, incorporam alguns elementos importantes sobre administrar arrays e de coleções1 em GeneXus. Pelo qual mostraremos alguns exemplos:

For to step: • inicio, fin são expressões numéricas• salto é uma constante numérica• var é alguma variável numérica• bloque é uma sucessão de comandos válidos da linguagem

Permite interagir certa quantidade de vezes: desde o valor início que toma a variável &var quando se ingressa ao loop, até o valor fim que toma a mesma quantidade de interações. De interação em interação a variável &var vai incrementando automaticamente numa quantidade igual a passo. O valor por default de salto é 1, senão especificarmos a cláusula step o incremento da variável será de um em um. O valor de salto pode ser negativo e nesse caso irá decrementando a variável de interação em interação.

ExemploFor &i = 1 to 5

&ok = PInvoicing.udp( &month )Endfor

__________________________________________________________________________

1 As coleções representam listas de tamanho variável. Serão vistas quando estudarmos o tipo de dados estruturado (SDT).

Page 203: 93909254 GENEXUS Heuristica Apostila Teorica

203

For in Expression:• Expression é qualquer expressão cujo valor seja uma coleção, vetor ou matriz. • var é uma variável que deve ter o mesmo tipo de dados que os elementos de Expression.

Esta estrutura de programação permite percorrer com menos código uma coleção ou uma variável vetor de uma ou mais dimensões. Se armazena na variável &var os valores de cada elemento da coleção, vetor ou matriz.

Para o caso de vetores de uma dimensão:

for &var in &varArray()… // code

Endfor

o código se expande (é equivalente) a:&x = 1

do while &x <= rows(&array())&var = &Array(&x)bloque&x += 1

enddo

No caso de duas dimensões:

for &var in &varMatrix()… // code

Endfor

o comando se expande (é equivalente) a: &x = 1 do while &x <= rows( &array() )

&e = 1do while &e <= cols( &array() )

&var = &array( &x, &e )bloque&e += 1

enddo&x += 1

enddo

Também pode ser uma variável coleção de qualquer tipo, incluindo uma variável com a propriedade Collection em 'False' mas de um tipo de dados 'SDT collection' .

for &var in &collection...endfor

A expressão também pode não ser uma variável, por exemplo no caso do resultado de um DataProvider ou de um Procedure:

for &var in DataProvider(parms)...Endfor

for &var in Procedure(parms)...endfor

Considerações:

• Não é possível modificar os valores da coleção, vetor ou matriz na percorrida. Isto significa que alterações no valor de &var no alcance da estrutura, não afetam ao correspondente valor da &collection o do &array(&x), ou de &array(&x, &e)).

• Não é possível obter a posição da coleção/array/matriz durante a percorrida, para isto é necessário definir uma variável que atue como contador.

•Estas estruturas podem aninhar para percorrer vários arrays, matrizes ou coleções. Isto inclui o caso de que se chame uma Subrotina que também possui um For In Expression.

•Igual que em um For Each ou um Do While, é possível incluir comando que “corte” a percorrida, como Exit ou Return.

Page 204: 93909254 GENEXUS Heuristica Apostila Teorica

204

• Print• Utilizado para imprimir a saída de um Printblock definido no Layout

• Sintaxe: Print nomePrintBlock

• Header• Utilizado para definir o que se quer imprimir como cabeçalho de cada página da

listagem

• Sintaxe: Header

bloque

end

• Footer• Define as linhas de rodapé da página a ser impressa ao final de cada página do

procedimento.

• Sintaxe: Footer

bloque

end

Comandos de impressão

Aqui veremos alguns comandos de impressão, que permitem desenhar a saída do procedimento.

PrintOnde nomePrintBlock é o identificador de um Printblock do Layout. Não existindo no Layout um Printblock com esse nome, ao tentar salvar o objeto mostra-se uma mensagem de error informando sobre esta situação.

Desta forma implementa-se a impressão na saída dos Printblocks do Layout.

Quando o Printblock que se quer imprimir não contêm atributos, então este comando pode ser utilizado em qualquer lugar do Source.

Os atributos indicam acesso a base de dados e este acesso não pode ser realizado em qualquer lugar, somente dentro do comando específico para ele, isto é, o comando For each.

Portanto, não é correto escrever o comando print fora de um “For each” se o Printblock que desejamos imprimir contêm atributos.

A única exceção desta regra se produz quando os atributos do Printblock estão incluídos entre os parâmetros recebidos pelo procedimento, pois neste caso não é necessário acessar a base de dados para recuperar seus valores, visto que já vem instanciados.

HeaderAqui se define o que se quer imprimir como cabeçalho de cada página da listagem.Este cabeçalho é opcional. Se não for especificada, então as páginas da listagem não terão cabeçalho.

Exemplo: No procedimento que queríamos imprimir uma listagem com o código, nome e país de cada um dos clientes de nosso sistema, se queremos que em cada página da listagem apareça o cabeçalho: “CUSTOMERS REPORT”, então é suficiente escrever no Source:

HeaderPrint title

EndOnde “title” é o nome de um Printblock do Layout que contem este texto.

Page 205: 93909254 GENEXUS Heuristica Apostila Teorica

205

Também poderíamos ter escrito diretamente: Print title no início do Source, mas neste caso, se a listagem tem várias páginas, somente sairá impresso este texto na primeira. No outro caso, sairá em cada uma das páginas, como cabeçalho.

FooterDefine as linhas no rodapé da página a ser impressas ao final de cada página do procedimento.

Os comandos do bloque de código são executados quando se chega ao final de uma página.

Exemplo: Footer

print endOfPageTextend

onde endOfPageText é o nome de um Printblock do Layout

Page 206: 93909254 GENEXUS Heuristica Apostila Teorica

206

Desenho da saída

Existem alguns comandos para desenhar a saída do procedimento. Apresentamos aqui alguns efeitos da documentação.

MT nlines: nlines é o número de linha em que se quer começar a imprimir a listagem. Caso não seja especificado um valor se assume o valor por default que é 0.

MB nlines: nlines é o número de linhas que se deseja deixar como margem inferior.Caso não seja especificado um valor se assume o valor por default que é 6.

PL nlines: Seta o tamanho de página. O número de linhas que será impresso é o número especificado menos a margem de baixo (valor por default é 6). Ex: PL 66Seta o tamanho da página a 66 linhas, ainda que somente 60 linhas sejam impressas no form, com uma margem inferior de 6 linhas.

CP nlines: Se quiser na página atual um número de linhas maior ou igual ao número especificado, continua imprimindo na mesma página. Do contrario, passa a imprimir na próxima página (força um salto de página).

Lineno nlines: Define o número de linha onde vai ser impressa a seguinte linha. Se o número de linha atual é maior ao número especificado, então, a linha será impressa na próxima página. O de linhas começa na linha 0.

Eject: Força a um salto de página.

Noskip: Tem que estar imediatamente depois de um Printblock. Se o comando se encontra entre duas linhas, este comando as imprimirá na mesma linha.

Page 207: 93909254 GENEXUS Heuristica Apostila Teorica

207

Procedimentos PDF

• Configurar as propriedades:• Main Program = True

• Call Protocol = HTTP

• Report Output = ‘Only to file’

• Regra• Output_file( ‘xx.pdf’, ‘PDF’)

Em Web as listagens somente podem ser PDF e devem ser configuradas as propriedades e regras anteriores para que funcionem.

Definição de um objeto como main

Ao definir que um objeto é main (neste caso um procedimento, mas poderia ser uma transação, web panel, etc.), GeneXus gera um programa executável com a lógica do objeto mesmo e a de todos os objetos chamados direta ou indiretamente por ele.

O programa executável gerado pode compilar e executar de forma independente, isto é, ao selecionar Build / Run se verá como programa independente do Developer Menu e poderácompilar-se e executar-se.

A definição de um objeto como main se realiza editando as propriedades do objeto, e configurando a propriedade Main program do mesmo com valor True.

Page 208: 93909254 GENEXUS Heuristica Apostila Teorica

208

Condições

• Permite especificar condições globais que devem ser cumpridas para que os dados sejam recuperados.

• Exemplo:

Nesta seção se permite estabelecer condições que devem cumprir os dados para ser recuperados.

Uma “condição” é equivalente a cláusula “where” do comando for each (tem a mesma sintaxe) com uma diferença: enquanto a cláusula “where” está ligada à um For each específico - aquele ao que pertence -, as “condições” estão ligadas à todos os For each do Source que tenha sentido aplicá-las.

E para que For eachs tem sentido aplicá-las?As Condições geralmente envolvem atributos. Se na tabela estendida de um For each encontra-se algum dos atributos que interferem numa “condição”, então a mesma pode ser aplicada à este For each para filtrar os dados ficando unicamente com aqueles que satisfaçam tal condição.

Na listagem de navegação do procedimento indicam-se os For eachs que aplicam-se a cada condição das especificadas na seção “Conditions”.

Se no Source do procedimento “PrintCustomers” temos:

For eachPrint customer

Endfor

Então ao especificar as condições que se mostram no slide, estaremos filtrando os clientes, deacordo com as condições (é equivalente ter as condições como “where”).

Page 209: 93909254 GENEXUS Heuristica Apostila Teorica

209

Condições• Sendo o Source do procedimento é:

For eachPrint customer

Endfor

For eachPrint invoice

Endfor

For eachPrint product

Endfor

For eachwhere CustomerName>=&start

Print customerEndforFor eachwhere CustomerName>=&startwhere InvoiceId < 100

Print invoiceEndforFor each

Print productEndfor

Conditions: CustomerName >= &Start;InvoiceId < 100;

onde:• “customer” é um Printblock que contem os atributos CustomerId, CustomerName, CountryName

• “invoice” é um Printblock que contem os atributos InvoiceId, CustomerId, CustomerName, InvoiceDate, InvoiceTotal

• “product” é um Printblock que contem os atributos ProductId, ProductDescription, ProductStock

Se o procedimento anterior tem definido as condições mostradas acima, o procedimento seráequivalente a um que não tiver “condições” e com o Source que se mostra a direita.

Observemos que neste caso as condições se traduzem em cláusulas where mas que se aplicam somente aos For eachs para os que tem sentido aplicá-las. Na tabela estendida do último For each não se trabalha com nome de cliente, nem com identificador de fatura. Não tem sentido aplicar as condições neste For each já que não existe nenhuma relação. No primeiro, somente tem sentido aplicar se utilizar CustomerName e não a outra.

ObservaçãoOs atributos envolvidos nas “condições” não participam na determinação das tabelas base dos For eachs do Source (a diferença dos filtros que se especificam mediante cláusulas where).

Isto é, as tabelas base dos For eachs que apareçam no Source se determinam sem olhar as “condições”. Uma vez determinadas, nesse momento as condições são examinadas para determinar a quais For eachs se aplicam e a quais não.

O mesmo ocorre com os atributos recebido como parâmetro. Aplicam como filtro global por igualdade para os For eachs que tenha sentido, mas não participam na determinação das tabelas base.

Page 210: 93909254 GENEXUS Heuristica Apostila Teorica

210

• Formas de filtrar os dados:

• Cláusulas Where

• Condições

• Regra Parm (Atributos recebidos como parâmetros)

Exemplo: Parm(Att1 ... Attn)

Filtros na navegação

Participam na determinação da tabela base

NÃO participam na determinação da tabela base

Resumimos aqui as distintas formas de filtrar em um procedimento a informação da base de dados a ser recuperada:

a. cláusulas whereb. condiçõesc. parm( att, ..., att )

Estudemos as diferenças e similaridades entre elas.

1. As cláusulas where aplicam exclusivamente ao For each em que se encontram, enquanto que os filtros especificados como condições ou os que ficam determinados pelos atributos na regra parm são globais, isto é, aplicam a todos os For eachs do Source em que faça sentido aplicá-las.

2. Os filtros que ficam determinados ao receber atributos na regra parm são filtros por igualdade, isto é, para os For eachs que tenha sentido aplicá-los, se instanciarão unicamente os registros que tenham o mesmo valor que o recebido por parâmetro. Por outro lado, os filtros especificados nas cláusulas wherede um For each ou nas condições podem ser expressões booleanas quaisquer, incluso compostas.

3. Enquanto que os atributos que aparecem nas cláusulas where participam na determinação da tabela base do For each onde se encontram, os que aparecem nas condições ou na regra parm não o fazem. São aplicados ASSIM que determinadas as tabelas base dos For eachs do Source.

Page 211: 93909254 GENEXUS Heuristica Apostila Teorica

211

Objeto Data Selector

DS

Page 212: 93909254 GENEXUS Heuristica Apostila Teorica

• É um objeto GeneXus que permite armazenar um conjunto de ordens, filtros, defined by, com o objetivo de ser “referenciado” em diferentes consultas e cálculos, permitindo assim reutilizar navegações

Data Selectors - Conceito

CRIAMOS O DATA SELECTOR COM DITO FILTRO (+ ORDER + DEFINED BY)…E O REFERENCIAMOS A PARTIR DOS LUGARES NECESSÁRIOS

Em vários objetos, se repete a necessidade de consultar os clientes ativos (CustomerStatus= “Active”)Por exemplo:

• Procedimento que imprime clientes ativos, agrupados por sexo• Procedimento que aplica um desconto, somente para clientes ativos• Web Panel que mostra o total de vendas por cliente, somente dos clientes ativos

Exemplo:

Customer{CustomerId*CustomerNameCustomerAddressCustomerGenderCustomerStatus

}

O atributo CustomerStatus está baseado em um domínio enumerado, Status, que possui 3 valores:•Active•On Hold•Closed

Os clientes ativos serão aqueles que tenham o valor Status.Active.

Page 213: 93909254 GENEXUS Heuristica Apostila Teorica

Data Selectors - Definição

• Criar o objeto de tipo “Data Selector”, dar um nome e definir:

A estrutura consta de:

• Parameters: Parâmetros recebidos a partir da “chamada” do Data Selector, para serem usados em condições

• Conditions: Condições para filtrar os dados a serem recuperados• Orders: Ordens condicionais (cada ordem com seus atributos separados por vírgula e when opcional)• Defined by: Atributo ou lista de atributos que participam na definição da tabela base final

Page 214: 93909254 GENEXUS Heuristica Apostila Teorica

Data Selectors - Exemplo

Primeiro exemplo apresentado (Cont.): Em vários objetos de uma KB, se deseja consultar os clientes ativos

CustomerStatus= Status.Active

Exemplo:

Customer{CustomerId*CustomerNameCustomerAddressCustomerGenderCustomerStatus

}

Depois de definir um Data Selector, ele pode ser referenciado em:

• Comandos For Each• Grupos de Data Providers• Fórmulas Aggregate• Grids em Web Panels

A forma de referenciar um Data Selector dependerá a partir de qual caso se deseja chamar. Veremos a sintaxe para cada caso.

Page 215: 93909254 GENEXUS Heuristica Apostila Teorica

Data Selectors - Benefícios

• Economia e reutilização de código: A definição é feita uma vez e se reutiliza em várias consultas e cálculos na KB.

• Facilitam a manutenção: A definição é alterada num único lugar e a alteração é aplicada automaticamente em todos os lugares da KB que forem utilizados.

• Otimizam o conhecimento: Facilitam o treinamento dos novos funcionários.

Page 216: 93909254 GENEXUS Heuristica Apostila Teorica

Data Selectors – UsosEm For Each…

� Com cláusula USING: intervém na determinação da tabela base.

� Com operador IN: não intervém na determinação da tabela base.

Duas maneiras de uso:

• Com cláusula USING• Com operador IN na cláusula WHERE

Importante:

• Um Data Selector sempre tem tabela base.

• Dependendo da forma que for utilizado, os atributos presentes na definição do Data Selector intervém ou não na determinação da tabela base do For Each, Grupo, Grid ou Fórmula:

Page 217: 93909254 GENEXUS Heuristica Apostila Teorica

Data Selectors – UsosEm For Each…

For Each com cláusula USING

Sintaxe:

Exemplo 1:

Exemplo 2:

Isto se Expande a:

For Each USING DataSelectorName([[parm1 [,parm2 [, ..] ])……

EndFor

For Each USING ActiveCustomers()……

EndFor

For Each USING ActiveCustomers()Where CountryName = "Uruguay"

…EndFor

For EachWhere CustomerStatus = Status.ActiveWhere CountryName = "Uruguay"

…EndFor

ATRIBUTOS DO DATA SELECTOR PARTICIPAMNA DETERMINAÇÃO DA TABELA BASE DO FOR EACH

Nota:

A performance será a mesma escrevendo 2 where no For Each que seja referenciado um Data Selector no For Each (que tem definida uma condição) + um where no For Each.

GeneXus sempre tratará de otimizar o código gerado, todavia não mais por utilizar o conceito de Data Selectors, jáque seu objetivo como explicamos, é: centralizar o conhecimento reutilizável em uma única definição e depois referenciar essa definição em todas as consultas e cálculos da KB que aplique.

Page 218: 93909254 GENEXUS Heuristica Apostila Teorica

For Each com operador IN (em cláusulas WHERE)

Sintaxe:

Exemplo:

Definição do Data Selector “InvoicesByDate”:

For Each Where <attribute> IN DataSelectorName([[parm1 [,parm2 [, ..] ])…

EndFor

For EachWhere CustomerId IN InvoicesByDate(&FromDate, &ToDate)…

EndFor

Data Selectors – UsosEm For Each…

CONSISTE NUMA CONSULTA A PARTE / INDEPENDENTE DO FOR EACH

O atributo que antecede o operador IN deve pertencer a tabela estendida da tabela base do Data Selector

TABLA BASE: INVOICE

• É GERADO UM SELECT PARA O DATA SELECTOR, INDEPENDENTE DO SELECT QUE SE GERA PARA O FOR EACH

•ATRIBUTOS DO DATA SELECTOR NÃO PARTICIPAM NA DETERMINAÇÃO DA TABELA BASE DO FOR EACH

Neste exemplo:

- A tabela base do Data Selector é: INVOICE

- O atributo que antecede ao operador IN pertence a tabela estendida de INVOICE (CustomerId)… e a consulta associada ao Data Selector devolverá uma lista de valores correspondentes a dito atributo (devolve “uma lista de clientes” que tem faturas na faixa de datas dada).

- O For Each tem sua tabela base determinada pelos atributos incluídos no For Each e sem levar em consideração a informação armazenada no Data Selector.

- O For Each navegará sua tabela base e estendida, filtrando os registros que contenham algum dos clientes da listadevolvido pelo Data Selector.

Page 219: 93909254 GENEXUS Heuristica Apostila Teorica

Data Selectors – UsosEm Fórmulas Aggregate…

• É possível utilizar Data Selectors em fórmulas Aggregate tanto globais como locais

• Sintaxe:

• Exemplo:

NomeFormulaAggregate '(' <Expressão> ',' [<CondiçãoAgg>] ',' [<ValorDef>]')'

Find | Max | Min | Sum | Count | Average

Expressão de busca, maximizada, minimizada, somada ou média

[<CondiçãoBusca] ['USING' <DataSelector> '(' <Parâmetro1> ',' <Parâmetro2> ',' <Parâmetro3>')']

Valor a ser devolvido caso não exista registros que cumpram com <CondiçãoAgg>

atributo fórmula ����quantidade de clientesativos do país

Considerações referente a sintaxe das fórmulas Aggregate:

Como foi detalhado no slide, na sintaxe das fórmulas Aggregate a expressão corresponde a expressão de busca, maximizada, minimizada, somada ou média. Pode ser um atributo (armazenado ou fórmula) ou bem uma expressão que envolve atributos, constantes, variáveis.

Todavia tem que levar em consideração que:

- Variáveis somente podem estar envolvidas nas fórmulas locais- Para Sum e Average, o resultado da Expressão deve ser um valor numérico- Unicamente para o caso de Count, não vale uma Expressão e sim um atributo

Page 220: 93909254 GENEXUS Heuristica Apostila Teorica

Data Selectors – UsosConsiderações

• Podem ser incluídos tanto variáveis como atributos nos parâmetros do Data Selector.

• Incluir atributos implica que tenha um filtro por igualdade.

• Observar que na mesma definição de um Data Selector, terá tabela base e certo comportamento, ou não terá tabela base e outro comportamento dependendo de como seja “chamado” no contexto que for usado.

Page 221: 93909254 GENEXUS Heuristica Apostila Teorica

221

FÓRMULAS LOCAIS

Page 222: 93909254 GENEXUS Heuristica Apostila Teorica

222

• Além de definir fórmulas associadas aos atributos (globais, a nível da KB) também é possível definir fórmulas no próprio código

• Chamamos neste caso de fórmulas: fórmulas inline ou fórmulas locais

• É possível definir fórmulas inline = locais � no source de procedimentos, subrotinas, eventos, etc.

• O Comportamento depende:

1) Dentro do For Each2) Fora do For Each

Fórmulas LocaisGeneralidades

Page 223: 93909254 GENEXUS Heuristica Apostila Teorica

223

• Tabela base da fórmula = Tabela base do For Each

• É possível incluir na definição da fórmula:

- atributos da tabela base da fórmula + estendida- atributos da tabela navegada pela fórmula + estendida- variáveis

• Exemplo:

Fórmulas LocaisDentro do For Each

For Each order CountryId &NumberCustomers = Count(CustomerName)

EndForATRIBUTOS QUE PERTENCEM NA DEF. DA FÓRMULA ���� NÃO PARTICIPAM NA DETERMINAÇÃO DA TABELA BASE DO FOR EACH

TABELA BASE FOR EACH = COUNTRY

TABELA BASE FÓRMULA = COUNTRY

TABELA NAVEGADA FÓRMULA = CUSTOMER

ATRIBUTO EM COMUM: CountryId

Outro exemplo de codificação possível é o que segue, na qual a fórmula é definida no próprio where do For Each, para filtrar por dito cálculo:

For each order CountryIdwhere Count(CustomerName)>50

…Endfor

Page 224: 93909254 GENEXUS Heuristica Apostila Teorica

224

• Se não estiver posicionado em nenhuma tabela no momento de disparo da fórmula �não tem tabela associada a fórmula

• É possível incluir na definição da fórmula:

- atributos de tabela a ser navegada + tabela estendida- variáveis

• Neste caso de uso, não tem filtros implícitos:

• Consideração importante: O disparo da fórmula é realizado no início do grupo onde se encontra. Portanto:

&CustomerId = 1&total = Sum(InvoiceTotal, CustomerId = &CustomerId)

Solução:&CustomerId = 1 sub ‘calctotal’do ‘calctotal’ &total = Sum(InvoiceTotal, CustomerId = &CustomerId)

endsub

For eachdefined by CustomerName

&total=sum(InvoiceTotal) VERSUS &total=sum(InvoiceTotal)

EndforSOMA AS FATURASFILTRANDO POR CLIENTE

SOMA TODAS AS FATURAS

&CustomerId não tem valor

Fórmulas LocaisFora do For Each

Consideração importante

Uma fórmula se dispara quando começa o grupo que a contêm.

Isto significa que se possui uma fórmula definida com seus parâmetros em determinada linha de código, os valores dos parâmetros serão aqueles que foram lidos quando o grupo foi executado na base de dados. Então, se o grupo foi executado na base dados, e depois disso atribuir valores aos diferentes parâmetros envolvidos na definição da fórmula, os valores dos parâmetros que serão levados em consideração não serão os que você atribuiu; pelo contrário serão os lidos quando se executou o grupo que contem a fórmula na base de dados.

E quando os grupos são executados?

- Quando começa um programa- Quando começa um For Each- Depois de um Endfor - Quando começa uma subrotina ou um evento

Em particular como neste caso estamos explicando fórmulas locais definidas fora de comandos For Each, os itens aplicados são 1. 3. e 4.

O mesmo ocorre com as variáveis. Os valores das variáveis que são considerados no momento de disparar as fórmulas, são os valores que as variáveis tem atribuído quando o grupo que contem a fórmula é executada. Se escrevermos o seguinte código:

&CustomerId = 1&total = Sum(InvoiceTotal, CustomerId = &CustomerId)

Page 225: 93909254 GENEXUS Heuristica Apostila Teorica

225

A variável &CustomerId não terá valor quando a fórmula é disparada.

Isto pode ser resolvido assim:

&CustomerId = 1

do ‘calctotal’

Sub ‘calctotal’&total = Sum(InvoiceTotal, CustomerId = &CustomerId)

Endsub

Já que assim obtemos um novo começo de grupo (quando a subrotina começa), e nesse momento a variável já está carregada com o valor desejado. De tal maneira que com esta solução, quando a fórmula é executada a variável &CustomerId terá valor 1.

Page 226: 93909254 GENEXUS Heuristica Apostila Teorica

226

Tipos de dados estruturados

SDT

Page 227: 93909254 GENEXUS Heuristica Apostila Teorica

227

SDT: Introdução

• Linguagens de programação gerenciam:• Tipos de dados simples (Numeric, Character, etc.)

• Tipos de dados compostos.

• Exemplo de Tipos de dados compostos (registros ou tipos de dados estruturados)

Type Client = Record

Name: Character(30)

Country: Character(20)

City: Character(20)

Phones: Record

Home: Character(15)

CellPhone: Character(15)

end;

end;

Depois são definidas as variáveis com este tipo de dados e se trabalha com elas...

Page 228: 93909254 GENEXUS Heuristica Apostila Teorica

228

SDT em GeneXus

• São criados como qualquer outro objeto GeneXus.

• Editor similar ao das estruturas de transações.

• SDT se compõe de: membros, subestruturas e coleções:

botãodireito

O editor de tipos de dados estruturados é similar ao editor de transações.

Contem:Propriedade Name, com o nome que identifica ao membro, subestrutura ou coleção.Propriedade Type, na qual se deve selecionar um tipo de dados simples, um domínio, ou um tipo de dados estruturado que já tenha sido definido na KB (propriedade Type somente adquire valor se estiver definindo um membro e não uma subestrutura ou coleção).Propriedade Is Collection, para indicar se o membro representa uma lista (em seguida veremos um exemplo).

Observe que uma subestrutura é um membro composto, ao invés de ser um simples. Em particular ele também é um tipo de dados estruturado.

Fazendo botão direito sobre um membro da estrutura, se mostra a janela que se vê a esquerda, onde se pode inserir outro membro, ou uma subestrutura.

Tip: Se desejar criar um SDT com exatamente a mesma estrutura que a de uma transação, então ao invés de definir um a um todos os membros, subestruturas e coleções, basta arrastar (fazer Drag & Drop) o nome da transação desde o Folder View para a estrutura em edição do SDT. Da mesma forma, se desejar que um membro da estrutura corresponda a um atributo, pode selecionar e arrastar o atributo desde o Work With Attributes (janela editável da opção View do menu de GeneXus) ou inserir com o diálogo Insert/Attribute do menu de GeneXus.

Page 229: 93909254 GENEXUS Heuristica Apostila Teorica

229

• Exemplo contendo coleção:

Um país tem muitas cidades...

SDT em GeneXus

Marcando o check box Is Collection se abrirá um ramo da estrutura como se poder, onde é pedido dois nomes: o da coleção em si, e o de cada item da mesma.

Como veremos em seguida, quando se define uma coleção, junto com o SDT se estará criando implicitamente outro, que corresponderá aos itens da coleção.

Isto ocorre desta forma para que depois possa ser definido uma variável do tipo de dados do item, para depois agregá-la para a coleção.

Page 230: 93909254 GENEXUS Heuristica Apostila Teorica

230

SDT: Utilização

• São utilizadas através de variáveis.

• Os atributos não podem ser definidos como SDT.

Id 1

Name Brasil

Cities •

CityName Goiânia

CityName Santa Catarina

CityName São Paulo

&country

A direita pode se ver o diálogo de propriedades de uma variável &country que se está definindo dentro de algum objeto.

O SDT Country definido na KB tal como se aprecia na página anterior, da lugar a criação de dois outros correspondentes aos itens da coleção “country.City”. Este último é devido ao caso de poder querer definir uma variável somente desse tipo de dados, para depois agregá-la com o método Add que já mencionaremos, na coleção.

Observe que a variável &country foi definida do tipo de dados “country” que aparece na lista obtida ao fazer clique no combo box da propriedade “Data Type” do diálogo de definição de propriedades da variável.

Page 231: 93909254 GENEXUS Heuristica Apostila Teorica

231

SDT: Utilização

• Para dados não repetitivos, cada membro é acessado pelo nome, como propriedade variável.

Name Julia Silveira

Country Brasil

City São Paulo

Phones Home 555-155.55.44

CellPhone 092-155.12.33

&client.Name = ‘Julia Silveira&client.Country = ‘Brasil&client.City = ‘’São Paulo&client.Phones.Home = ...&client.Phones.CellPhone = ...

Page 232: 93909254 GENEXUS Heuristica Apostila Teorica

232

SDT: Utilização• Exemplo: Transação que registra os recibos efetuados aos clientes e SDT

baseado na transação:

For each where BillId = 7&bill.BillDate= BillDate&bill.CustomerId = CustomerId&bill.CustomerName = CustomerName&bill.BillInvoicePeriodStartDate = BillInvoicePeriodStartDate&bill.BillInvoicePeriodEndDate = BillInvoicePeriodEndDate&bill.BillAmount = BillAmount

endfor

Na proc. se carrega &bill com dados dorecibo 7 da BD...

...poderia devolver:parm(..., out: &bill)

...da tabela BILL

drag&

drop

Aqui se apresenta um exemplo com o qual continuaremos trabalhando. Agregamos a nossa realidade uma transação de recibos. Vamos supor que uma vez no mês, se lança um processo de faturamento, se escolhe período de faturamento (usualmente todo o mês anterior) se contabilizam todas as faturas efetuadas por cliente, e se gera um recibo para o mesmo (autonumber). A geração do recibo será automática (será realizada pelo nosso sistema); esse é um tema que veremos em breve.

Por agora, vamos supor que necessitamos um procedimento que devolva os dados de um recibo dado (por exemplo, o de id. 7). Uma opção é acessar mediante um for each a tabela BILL criada a partir da transação com o mesmo nome, e junto com a regra parm:

parm( out: BillDate, out: CustomerId, out: CustomerName, out: BillInvoicePeriodStartDate, out: BillInvoicePeriodEndDate, out: BillAmount);

implementar o pedido.

A outra opção, é devolver toda essa informação em somente uma variável estruturada!

parm( out: &bill);

carregada como se mostra acima. Para isso se define um SDT baseado na transação Bill (os SDTs não podem ter o mesmo nome que uma transação, razão pela qual a chamamos BILL_SDT). Para não ter que ingressar um por um os membros do SDT com o mesmo nome que os atributos da transação, basta arrastar a transação Bill desde o Folder View, dentro da estrutura do SDT e automaticamente se inicializará como se mostra acima.

Page 233: 93909254 GENEXUS Heuristica Apostila Teorica

233

SDT: Utilização• E se quisermos devolver uma lista de recibos?

• Opção 1: não modificar o SDT e agregar a variável &bills coleção:

For each where... &bill.BillDate = BillDate&bill.CustomerId = CustomerId&bill.CustomerName = CustomerName&bill.BillInvoicePeriodStartDate = BillInvoicePeriodStartDate&bill.BillInvoicePeriodEndDate = BillInvoicePeriodEndDate&bill.BillAmount = BillAmount&bills.Add( &bill )&bill = new Bill_SDT()

endfor

Vamos supor que queremos devolver uma lista de recibos (por exemplo, os que foram efetuados numa faixa de datas dado).

Page 234: 93909254 GENEXUS Heuristica Apostila Teorica

234

SDT: Utilização

&bills

&bill new

add

&bills.Add( &bill )

&bill = new Bill_SDT()

&bill.BillDate= BillDate&bill.CustomerId = ...&bill.CustomerName = ...&bill.BillInvoicePeriodStartDate = ...&bill.BillInvoicePeriodEndDate = ...&bill.BillAmount = ...

Baixo nível! Não existe outra forma?

Tem que pedir novo espaço de memória para a variável &bill, para a seguinte iteração.

Como veremos em breve, existe um modo muito mais simples, de nível mais alto, DECLARATIVO, de obter a coleção de SDTs carregada, sem ter que nos preocuparmos em realizar as operações de baixo nível, como agregar uma variável na coleção e pedir memória...

Page 235: 93909254 GENEXUS Heuristica Apostila Teorica

235

SDT: Utilização em Data Provider

Data Provider: procedimento especializado, devolve info estruturada

Bills{

Bill where ...{

BillDate= BillDateCustomerId = CustomerIdCustomerName = CustomerNameBillInvoicePeriodStartDate = BillInvoicePeriodStartDateBillInvoicePeriodEndDate = BillInvoicePeriodEndDateBillAmount = BillAmount

}}

...este modo declarativo, portanto de alto nível, de carregar uma coleção de SDTs se conhece com o nome de Data Provider. Podemos pensá-lo como um procedimento especializado, que devolverá sempre informação estruturada (seja simples ou como coleção).

Aqui apresentamos o exemplo, que depois ampliaremos quando entrarmos de fato neste tema.

Page 236: 93909254 GENEXUS Heuristica Apostila Teorica

236

SDT: Utilização• Opção 2: modificar o SDT para que seja uma coleção e depois se

trabalha da mesma forma, definindo as variáveis:

&bills

&bill

Page 237: 93909254 GENEXUS Heuristica Apostila Teorica

237

SDT: Utilização

• Para dados repetitivos, se acessa a cada item mediante comando:

For &var in expression

code

endfor

&var: variável de tipo de dados A expression: expressão cujo tipo de dados

é coleção de A, ou array de A

For &bill in &billsmsg( &bill.Id.ToString() )msg( ‘Name:’ + &bill.CustomerName )...

endfor

Exemplo: A = SDT

É possível incluir comandos de “corte” da percorrida, da mesma forma que em for each ou do while, como exit ou return.

A variável &var vai tomando os valores de cada posição da lista.

Não é possível obter a posição do item durante percorrê-la, para isto é necessário definir uma variável que atue como contador.

Como pode ser facilmente inferido, este comando é válido para coleções de qualquer tipo de dados, não somente SDTs.

Page 238: 93909254 GENEXUS Heuristica Apostila Teorica

238

SDT: propriedades

&cVar.Count() Retorna a quantidade de itens da coleção.

&cVar.CurrentItem() Quando uma variável SDT collection é mostrada no form (como grid) se permite selecionar o item selecionado com o mouse como linha do grid.

Os nomes dos membros de uma variável do tipo SDT collection são mostrados como propriedades:

Além disso, para variáveis collection:

As propriedades Count e CurrentItem somente estão disponíveis para variáveis SDT Collection.

Page 239: 93909254 GENEXUS Heuristica Apostila Teorica

239

SDT: operadores e métodos

&cVar.Add( &item [, Position]) Agrega o item a coleção na posição relativa especificada. Se omitir é agregada ao final. Position começa em 1.

&cVar.Clear() Elimina todos os itens da coleção

&var.Clone() Cria uma nova área de memória e copia os dados da variável nesta: &var1 = &var2.Clone() A

&var.FromXML( &xml ) Carrega variável SDT a partir da string contendo uma estrutura xml.

&cVar.Item( Position ) Retorna referência ao elemento com posição relativa Position

na collection.

&cVar.Remove( Position ) Elimina item que se encontre na posição especificada e corre um lugar todas as posições.

&cVar.Sort( memberName ) Ordena os elementos da coleção de acordo ao membro.

&var.ToXml() Retorna uma string com o formato XML dos dados da variável SDT (que pode ser collection): ml = &var.ToXml()

&var = new SDT() Retorna uma nova referência ou ponteiro ao SDT especificado

Aqui se apresentam a maioria dos métodos de tipos de dados estruturados.

Alguns se aplicam a variáveis SDT não coleção, se representam com &var, outros a coleções, se representam com &cVar.Para a lista completa, assim como exemplos, acessar ao wiki ou ao help da versão.

Page 240: 93909254 GENEXUS Heuristica Apostila Teorica

240

SDT: Exemplo

• Método ToXml:Name Julia James

Country Uruguay

City Montevideo

Phones Home 555-155.55.44

CellPhone 092-155.12.33

&xml = &client.ToXml()

<Client><Name> Julia James </Name><Country> Uruguay </Country><City> Montevideo </City><Phones>

<Home> 555-155.55.44 </Home><CellPhone> 092-155.12.33 </Home>

</Phones></Client>

Page 241: 93909254 GENEXUS Heuristica Apostila Teorica

241

SDT collection em FORM

• Ao inserir num form uma variável SDT collection:

aparece uma janela para selecionar os membros a serem inseridos

que serão apresentados como grid e será carregado automaticamente :

Pode selecionar-se do SDT os membros que se querem carregar como colunas do grid. Observe que em nosso caso temos omitido os membros CustomerId, BillInvoicePeriodStartDate e BillInvoicePeriodEndDate.

Page 242: 93909254 GENEXUS Heuristica Apostila Teorica

242

Objeto Data Provider

DP

Page 243: 93909254 GENEXUS Heuristica Apostila Teorica

243

DP: Cenário• Troca de informação hierárquica entre aplicações ou dentro de

uma mesma aplicação.

DataInterchange

APPLICATION A APPLICATION B

Sistemade

Faturamento

Sistemade

Devedores/Credores

envio de info dos recibos

BillId: 2516Customer: John DrottsDate: 12/12/2008Amount: 1000

FaBillId: 158Customer: Dane SmithDate: 12/12/2008Amount: 750

...

Vamos supor que a partir de nosso Billing System, queremos enviar um sistema de devedores e credores, uma listagem dos recibos correspondentes ao último faturamento. Se trata de informação hierárquica (a informação a ser enviada é a de recibos, cada um dos quais possui determinados dados).

XML é o formato mais usual de troca de informação hierárquica, ainda não sabemos o que vai acontecer no futuro neste aspecto (por exemplo se vai voltar a ser um formato comum ou formato Json).

Page 244: 93909254 GENEXUS Heuristica Apostila Teorica

244

Procedimentos “procedurais”• Como obter os recibos para um faixa de datas informada?

for each using ActiveCustomers()&bill.BillDate = &today&bill.CustomerName = CustomerName&bill.BillInvoicePeriodStartDate = &start&bill.BillInvoicePeriodEndDate = &end&bill.BillAmount = sum( InvoiceAmount, InvoiceDate>= &start and

InvoiceDate <= &end andInvoicePendingFlag )

&bills.Add( &bill )&bill = new Bill ()...

endfor

Utilizando um procedimento que receba a faixa de datas para o faturamento: &start e &end e devolva uma coleção de recibos: Bill

Tendo o mesmo SDT Bill que definimos quando estudamos os tipos de dados estruturados (ali o chamamos Bill SDT, aqui o chamaremos Bill), estamos utilizando um procedimento com os seguintes parâmetros:

parm( in: &start, in: &end, out: &bills );

sendo &start e &end variáveis de tipo Date que recebem a faixa de faturamento, e &bills uma variável collection do SDT Bill.

Observe que estamos utilizando o Data Selector ActiveCustomers para filtrar pelos clientes ativos e utilizando a fórmula inline sum, onde unicamente somamos os totais daquelas faturas que pertencem ao cliente da atual iteração do For each e cujas datas se encontrem na faixa informada e tenham o valor True no atributo Booleano InvoicePendingFlag.

Este atributo será alterado a False uma vez que a fatura foi processada dentro do processo de geração de recibos que iniciamos aqui mas que completaremos mais adiante, quando estudarmos as formas de atualizar a informação da base de dados (aqui somente estamos obtendo a informação dos recibos, mas ainda não os registraremos na base de dados... ).

Page 245: 93909254 GENEXUS Heuristica Apostila Teorica

245

• Linguagem de Input• Linguagem de Transformação• Linguagem de Output

Procedimentos “procedurais”

Transformation OUTPUTINPUT

Exemplo:Situado dentro do código

Qual o propósitodo

procedimento?

For each using ActiveCustomers()&bill.BillDate = &today&bill.CustomerName = CustomerName&bill.BillInvoicePeriodStartDate = &start&bill.BillInvoicePeriodEndDate = &end&bill.BillAmount = sum( InvoiceAmount, ...)&bills.Add( &bill )&bill = new Bill()

endfor

Todo procedimento toma um Input, e mediante alguma transformação, obtêm um Output.

Para obter o Input tendo certa linguagem (em GeneXus se trata da base de dados, basta nomear os atributos, como pode ser visto no exemplo, a direita das atribuições; assim como também se obtêm os parâmetros). Para realizar a Transformação possui outra linguagem (o código que podemos ver no exemplo) e depois para expressar o Output outro mais.

Como pode ver-se, no caso dos procedimentos GeneXus, tanto o Input como o Output se encontram situados dentro do próprio código de Transformação. Pode se dizer que o foco está colocado na transformação.

Desta forma o propósito do procedimento, sua saída, fica obscura dentro desse código, que mescla: • elementos de saída, • com elementos de transformação (em nosso caso, o comando for each, o método add e o operador new, que implementam o armado da coleção de recibos) • e com elementos de entrada.

Page 246: 93909254 GENEXUS Heuristica Apostila Teorica

246

• Linguagem de Input• Linguagem de Transformação• Linguagem de Output

Bills using ActiveCustomers(){

Bill{

BillDate = &todayCustomerName = CustomerName

BillInvoicePeriodStartDate = &start

BillInvoicePeriodEndDate = &endBillAmount = sum( InvoiceAmount, ...)

}}

Procedimentos “declarativos”

OUTPUTINPUT

FORMAT

TXTHTMLXMLJSONSDT...

Data Provider

hierarchical structure

Transformation

Propósito claro

BillsBill

BillDate: 12/12/08CustomerName: John Drotts...BillAmount 1000

BillBillDate: 12/12/08 CustomerName: Dane Smith...BillAmount: 750

...

Com um Data Provider, o foco está situado na linguagem de saída: observe que é indicado numa estrutura hierárquica do que é composto esse Output.

Depois, para cada elemento da estrutura hierárquica, terá que indicar no Source do Data Provider, como se calcula.

Portanto, basta observar o lado esquerdo para deduzir qual será a estrutura resultante.

Depois, é suficiente indicar o formato desejado para essa estrutura hierárquica resultante...

Page 247: 93909254 GENEXUS Heuristica Apostila Teorica

247

Procedimentos “declarativos”

BillsBill

BillDate: 12/12/08 CustomerName: John Drotts...BillAmount: 1000

BillBillDate: 12/12/08CustomerName: Dane Smith...BillAmount: 750

...

OUTPUTINPUT

FORMAT

TXTHTMLXMLJSONSDT...

Data Provider

hierarchical structure

Transformation

<Bills><Bill>

<BillDate>12/12/08</BillDate><CustomerName>John Drotts</CustomerName>...<BillAmount>1000</BillAmount>

</Bill><Bill>

<BillDate>12/12/08</BillDate><CustomerName>Dane Smith</CustomerName>....<BillAmount>750</BillAmount>

</Bill>

...</Bills>

Bill

Bill

Bills

BillDate 12/12/08

CustomerName John Drotts

... ...

BillAmount 1000

BillDate 12/12/08

CustomerName Dane Smith

... ...

BillAmount 750

• Linguagem de Input• Linguagem de Transformação• Linguagem de Output

Depois, uma mesma informação estruturada, pode ser representada utilizando diferentes formatos existentes.

Essa é a idéia do Data Provider. Se num futuro aparecer um novo formato de representação de informação estruturada, o Data Provider continuará sendo o mesmo. GeneXus implementará o método de transformação para esse formato, e somente terá que utilizá-lo.

Page 248: 93909254 GENEXUS Heuristica Apostila Teorica

248

DBDB

INPUT

Estruturas hierárquicasem GeneXus?

SDTs

Data Providers

Bill

BillBillDate 12/12/08

CustomerName John Drotts

... ...

BillAmount 1000

BillDate 12/12/08

CustomerName Dane Smith

... ...

BillAmount 750

CustomerId CustomerName CustomerStatus

1542 John Drotts A

1543 Dane Smith A

... ... ...

OUTPUT

invoices...

Até aqui fizemos uma análise descritiva. Surge a seguinte pergunta: Como em GeneXus representamos as estruturas hierárquicas de dados?

A saída de um Data Provider será um SDT (ou uma coleção de SDTs).

Depois, com essa saída se realiza o desejado, em particular, convertê-la ao formato XML, com o método toXml dos SDTs.

Vejamos como declaramos a saída... não será da forma convencional (como parâmetro de out da regra parm)...

Page 249: 93909254 GENEXUS Heuristica Apostila Teorica

249

Data Providers

Bill

BillBillDate 12/12/08

CustomerName John Drotts

... ...

BillAmount 1000

BillDate 12/12/08

CustomerName Dane Smith

... ...

BillAmount 750

OUTPUT

Aqui vemos para o exemplo que estamos estudando, que tendo o SDT definido Bills, collection, que coincide com a estrutura que se infere do Source do Data Provider ‘GetBills’, terá que declarar esse SDT na propriedade Output do Data Provider.

Mas não é a única possibilidade ... veremos outra na página seguinte, onde terá sentido a propriedade Collection.

Page 250: 93909254 GENEXUS Heuristica Apostila Teorica

250

Data Providers

Bill

BillBillDate 12/12/08

CustomerName John Drotts

... ...

BillAmount 1000

BillDate 12/12/08

CustomerName Dane Smith

... ...

BillAmount 750

OUTPUT

Outra possibilidade (mesmo resultado):

Se ao invés de ter o SDT collection Bills, tivéssemos o que aparece acima, Bill, então, poderíamos programar o Source do Data Provider como vemos e depois configurar a propriedade Collection em ‘True’, e uma nova propriedade é aberta, Collection Name, que permitirá dar nome para a coleção.

Este Data Provider é equivalente ao anterior.

Observe que neste caso não é necessário colocar a raiz da hierarquia, Bills, que se infere a propriedade ‘Collection Name’. De todas as formas, mesmo não sendo requerido pode-se programar o Source da mesma forma que o anterior, isto é, com o grupo Bills iniciando a hierarquia.

Bills{

Bill using ActiveCustomers(){

...}

}

Nota: a cláusula using, assim como os where que veremos em seguida, o order, etc., poderão ser especificadas tanto no grupo Bills, como no grupo Bill, em casos como este. Em seguida voltaremos nesse tema.

Page 251: 93909254 GENEXUS Heuristica Apostila Teorica

251

Data Provider

• Objetivo: Retorno de dados estruturados.

• Com Procedimento: o SDT é feito com operações de baixo nível.

• Com Data Provider: facilidade de escrita e clareza. Édeclarativo � independe de implementação.

� para devolver dados estruturados vamos utilizar um DP ao invés de um Procedimento.

Os Data Providers resolvem eficientemente um tipo de problema: aquele que consiste em retornar dados estruturados. Para esse tipo de problemas contávamos com os procedimentos, mas sua desvantagem evidente era que necessitávamos implementar a forma de armar essas estruturas com operações de baixo nível, como agregar um item a uma coleção com Add, e pedir memória (new). Assim mesmo, se tivesse que fazer cálculos complexos para dar valor a cada membro da estrutura, os elementos de saída estariam incorporados no código, o resultado do Procedimento não acaba sendo de fácil visualização.

Todos estes inconvenientes são evitados com Data Provider. O foco aqui está na saída, razão pela qual ao olhar já se sabe a estrutura do Output. Sendo declarativo, livre da forma que está implementada a carga do SDT. GeneXus se encarrega disso.

Quanto mais declarativo for uma ferramenta, mais fácil de programar, mais adaptável as mudanças, mais independente de uma implementação particular. GeneXus tende a ser o mais declarativo possível e cada vez programar menos ‘procedural’. A forma declarativa tira do programador o problema e passa para a implementação da ferramenta. Quanto mais inteligente for ferramenta, menos o programador precisa resolver o problema: basta enunciá-lo.

Page 252: 93909254 GENEXUS Heuristica Apostila Teorica

252

Data ProviderUtilização

• Da mesma forma que um procedimento que devolve informação estruturada:

Parm( in: par1, ..., in: parn, out: &bills ); &TheBills = GetBills( par1, ..., parn)

Procedimento ‘GetBills’ Objeto GeneXus

Data Provider ‘GetBills’

Parm( in: par1, ..., in: parn);

Output: BillCollection: TrueCollectionName: Bills

Objeto GeneXus

&TheBills = GetBills( par1, ..., parn)

udp

&xml = &TheBills.ToXml()

Um Data Provider também pode receber parâmetros através da regra parm, mas se diferencia de um procedimento onde todos os parâmetros podem ser de entrada/saída, aqui somente poderão ser de entrada.

Por outro lado, um procedimento que devolve informação estruturada é feito mediante uma variável que se carrega no código, e que deve declarar-se como de saída, no último parâmetro da regra parm.

Em um Data Provider, a declaração do tipo de dados de saída se faz mediante as propriedades Output, não na regra parm.

A chamada a partir de qualquer objeto GeneXus de um Data Provider é idêntica a chamada de um procedimento, isto é, com udp.

Lembre que ao chamar um objeto e não especificar o método de chamada, se assume udp.

A variável &TheBills deverá estar declarada no objeto GeneXus que se realiza a chamada. É a variável na qual se devolve o resultado. Lembre que se o SDT definido na KB é o correspondente aos itens individuais: Bill, (e não a coleção Bills), então a variável &TheBills será definida como Collection, de tipo de dados Bill.Depois, com a estrutura hierárquica devolvida pode, por exemplo, ser convertida ao formato desejado, como XML.

Importante:Como veremos, um Data Provider não somente pode retornar um SDT ou coleção de SDT, como também outro tipo, o Business Component, que também representa informação estruturada. Olhar esse tema para completar o conhecimento de Data Providers.

Page 253: 93909254 GENEXUS Heuristica Apostila Teorica

253

Linguagem de DP

• Componentes básicos:

• Grupos

• Elementos

• Variáveis

BillsInfo{

Bills{

Bill {

BillDate = &todayCustomerName = CustomerNameBillInvoicePeriodStartDate = &startBillInvoicePeriodEndDate = &endBillAmount = sum( InvoiceAmount, ... )&quantity = &quantity + 1

}}BillQuantity = &quantity

}

O exemplo que podemos ver aqui é parecido ao que trabalhamos. Agregamos o elemento BillQuantity. Tire uns instantes para pensar como deverá ser o SDT BillsInfo, para que se iguale com este Source. A esquerda o que apresentamos.O Source não precisa ser escrito da mesma forma que a estrutura do SDT. Se o SDT ter um membro collection de um item determinado, podemos omitir do Source o Item como grupo. Exemplo: com o SDT que temos acima, poderíamos ter escrito o Data Provider:

Billsnfo{

Bills{

BillDate = &todayCustomerName = CustomerNameBillInvoicePeriodStartDate = &startBillInvoicePeriodEndDate = &endBillAmount = sum (InvoiceAmount, ... )&quantity = &quantity + 1

}BillQuantity = &quantity

}

Com o mesmo resultado. GeneXus tem inteligência suficiente para matchear com o SDT.

Page 254: 93909254 GENEXUS Heuristica Apostila Teorica

254

Linguagem de DPGrupos

• Agrupam elementos, grupos, variáveis em um mesmo nível hierárquico.

• Pode ser repetitivo como pode não ser (ele tem inteligência para

determinar).

Será uma coleçãode muitos

BillsInfo{

Bills{

Bill{

…}

}BillQuantity = &quantity

}

BillsInfo{

Bills {

Bill{

BillDate = &todayCustomerName = CustomerName ...&quantity = &quantity +1

}} BillQuantity = &quantity

}

Page 255: 93909254 GENEXUS Heuristica Apostila Teorica

255

Linguagem de DPGrupos

• Um grupo repetitivo é análogo a um for each:• Determina a tabela base (da mesma forma que num for each)

• Tem disponível as mesmas cláusulas que um for each:

Ver mais adiante em opções avançadas

BillsInfo{

Bills{

Bill {

BillDate = &todayCustomerName = CustomerNameBillInvoicePeriodStartDate = &startBillInvoicePeriodEndDate = &endBillAmount = sum( InvoiceAmount, ...) &quantity = &quantity + 1}

}BillQuantity = &quantity&quantity = 0

}

[{[order] order_attributesi [when condi]}... | [order none] [when condx]][using DataSelectorName([[parm1 [,parm2 [, ...] ])][{where {conditioni when condi} |{attribute IN DataSelectorName([[parm1 [,parm2 [, ...] ]} }...][defined by att…]

No exemplo, o grupo de nome Bill será repetitivo. Por que? Para responder a pergunta, vamos fazer outra: e se for um for each, onde substitua os elementos da esquerda das atribuições por variáveis? Neste caso a presença de CustomerName a direita da segunda atribuição permite afirmar que tem tabela base: CUSTOMER.

Por tanto o grupo será repetitivo, iterando sobre a tabela CUSTOMER.

No exemplo que estamos trabalhando, temos a cláusula:

Bill using ActiveCustomers()

igual:

For each using ActiveCustomers()

se o atributo CustomerName não estivesse na segunda atribuição, da mesma forma seria com tabela base, pela presença do atributo CustomerStatus no Data Selector ‘ActiveCustomers’.

Observe que o grupo de nome BillsInfo, de forma diferente, não será repetitivo, não possui cláusulas associadas, e os elementos que contêm estão definidos a base de variáveis e não de atributos:

BillQuantity = &quantity&quantity = 0

E o que acontece com o grupo Bills? Observe que neste caso, é um grupo que somente possui outro grupo. O grupo contido será repetitivo, porque Bills será uma coleção de Bill. Por este motivo, o subgrupo Bill poderia ser omitido (somente deixar Bills) e que fique implícito. Deste modo, as cláusulas do grupo que permitem definir order, filtros, defined by, podem ser associadas a este grupo.

Page 256: 93909254 GENEXUS Heuristica Apostila Teorica

256

Linguagem de DPGrupos

• Grupos também podem ser repetidos:

Clients{

Client{

Name = ‘Lou Reed’Country = ‘United States’City = ‘New York’

}Client where CountryName = ‘Mexico’{

Name = CustomerNameCountry = CountryNameCity = CityName

}}

O resultado retornado seráuma coleção de N+1 itens: sendo N o número de clientes do México.

Se a condição estiver no grupo Clients, seria aplicada para os dois subgrupos Client. Por isso é permitido que as cláusulas operem nos grupos repetitivos (itens), e não somente do grupo que é coleção de itens.

Page 257: 93909254 GENEXUS Heuristica Apostila Teorica

257

Linguagem de DPElementos

• Um Elemento é um valor atômico no Output.

• Cada Elemento deve ser atribuído e sua sintaxe é igual a das fórmulas.

Exemplo:

Clients{

Client{

Name = CustomerNameActive = True if CustomerStatus = Status.Active; False otherwise;

}}

Page 258: 93909254 GENEXUS Heuristica Apostila Teorica

258

Linguagem de DPElementos

• Elementos e Atributos usualmente possuem o mesmo nome �notação mais compacta:

Exemplo:BillsInfo{

Bills {

Bill {

BillDate = &today CustomerName = CustomerNameBillInvoicePeriodStartDate = &start...

}}

}

BillsInfo{

Bills{

Bill {

BillDate = &todayCustomerName BillInvoicePeriodStartDate = &start...

}}

}

Page 259: 93909254 GENEXUS Heuristica Apostila Teorica

259

Linguagem de DPVariáveis

• Algumas vezes é necessário realizar cálculos internos:

Exemplo:

BillsInfo{

Bills{

&quantity = 0Bill {

BillDate = &todayCustomerNameBillInvoicePeriodStartDate = &startBillInvoicePeriodEndDate = &endBillAmount = sum( InvoiceAmount, ... )&quantity = &quantity + 1

}}BillQuantity = &quantity

}

Page 260: 93909254 GENEXUS Heuristica Apostila Teorica

260

Linguagem de DPGrupos: Opções avançadas

• Cláusula Default (~ When none)

• o grupo somente será de saída se o grupo precedente (com o mesmo nome) não estiver presente.

• Cláusulas de Paginação: Count e Skip• Para gerenciar quantos registros serão de saída.

• Cláusula NoOutput• em um Grupo significa que o grupo não deve estar presente na saída, mas

somente os seus elementos subordinados.

• Cláusula OutputIfDetail• Para o grupo cabeçalho contendo grupo com suas linhas: somente se apresenta o

primeiro de saída se tiver linhas.

• Cláusula Input• se necessita trabalhar com coleções (devolvidas por Procedimento ou Data

Provider) como Input do DP.

http://wiki.gxtechnical.com/commwiki/servlet/hwiki?Data+Provider+Language

A informação completa desse tema em inglês pode ser encontrada em nossa comunidade wiki, na página:

http://wiki.gxtechnical.com/commwiki/servlet/hwiki?Data+Provider+Language

Page 261: 93909254 GENEXUS Heuristica Apostila Teorica

261

Linguagem de DPGrupos: cláusula Default

• Cláusula Default: o grupo somente será de saída se o grupo precedente (com o mesmo nome) não estiver presente.

(~ When none em for each)

CurrentTaxesWhere TaxInitialDate >= today()Where TaxFinalDate <= today(){

VAT = TaxVATIncome = TaxIncome

}CurrentTaxes [Default]

{VAT = 0.7Income = 0.3

}

TaxInitialDate*TaxFinalDate*TaxVATTaxIncome

Tabela TAXES

Não se inclui no Output se não encontrou registro no dia de hoje

Page 262: 93909254 GENEXUS Heuristica Apostila Teorica

262

Linguagem de DPGrupos: cláusulas de paginação

• Count e Skip.

• Para gerenciar quantos registros serão de saída.

Customers {

Customer [Count = 20] [Skip = 100] {

Code = CustomerIdName = CustomerName

}}

São omitidos os 100 primeiros clientes e são incluído no Output os 20 seguintes.

Page 263: 93909254 GENEXUS Heuristica Apostila Teorica

263

Linguagem de DPGrupos: cláusula NoOutput

• Em um Grupo significa que o grupo não deverá estar presente na saída: somente os seus elementos subordinados.

Employees {

Employee{

Id = EmployeeIdName = EmployeeNameEarningInfo [NoOutput]Where IsAutorized(&UserId){

Salary = EmployeeSalaryBonus = EmployeeBonus

}}

}

<Employees><Employee>

<Id>123</Id><Name>John Doe</Name><EarningInfo>

<Salary>30000</Salary><Bonus>5000</Bonus>

</EarningInfo></Employee>...

</Employees>

<Employees><Employee>

<Id>123</Id><Name>John Doe</Name><Salary>30000</Salary><Bonus>5000</Bonus>

</Employee>...

</Employees>

…ao invés de…

Page 264: 93909254 GENEXUS Heuristica Apostila Teorica

264

Linguagem de DPGrupos: cláusula OutputIfDetail

• Cada item da coleção de saída tem um cabeçalho e algumas linhas: cláusula para o nível do grupo cabeçalho � somente serão apresentados na saída aqueles grupos que tenham linhas.

Countries{

Country [OutputIfDetail]{

Id = CountryIdName = CountryName

Customers{

Id= CustomerIdName = CustomerName&quantity = &quantity + 1

}Quantity = &quantity

}}

Se um país não possuir clientes associados � não aparece como item da coleção Countries na saída.

Tabla base: COUNTRY

Tabla base: CUSTOMER

Não mencionamos, mas de forma intuitiva podemos pensar, de ter um par de grupos “aninhados” (um grupo que, entre outras coisas, contêm outro), se cada um deve acessar a base de dados, então as tabelas base, assim como o critério de navegação são determinados exatamente da mesma forma que no caso de um par de for eachs anhidados.

Por esse motivo, no exemplo, o grupo Country possui tabela base COUNTRY; o grupo Customers possui tabela base CUSTOMER, e terá um join entre ambas tabelas na hora de recuperar a informação para carregar a coleção de países. Isto é, para cada registro de COUNTRY será carregada a informação de seus atributos CountryId e CountryName nos elementos Id e Name do item Country do SDT coleção “Countries” que estiver carregando, e depois percorrerá a tabela CUSTOMER filtrando por aqueles registros para os quaisCUSTOMER.CountryId = COUNTRY.CountryId, carregando para cada um os elementos Id e Name.

A presença da cláusula OutputIfDetail faz que somente se apresentam na saída aqueles países que possuam clientes associados. Se um país da base de dados não tiver nenhum cliente, então não será apresentado como item da coleção de saída, “Countries”.

Page 265: 93909254 GENEXUS Heuristica Apostila Teorica

265

Linguagem de DPCláusula Input

• Até aqui assumimos que o Input vinha da BD; mas também énecessário outro tipo de entrada. Por exemplo, a saída de um Procedimento ou Data Provider. A forma mais clara de trabalho é através de variáveis, que uma vez atribuídas são manipuladas de forma usual:

• Mas se for necessário trabalhar com uma coleção é necessário utilizar a cláusula Input…

&var = Proc.udp( parm1, ..., parmn)

&SdtVariable = DataProvider( parm1, ..., parmn )

Page 266: 93909254 GENEXUS Heuristica Apostila Teorica

266

Linguagem de DPCláusula Input

• Para trabalhar com coleções.

VerySimple{

Month Input &i = 1 to 12{

MonthNumber = &i}

}

CustomersFromAnotherDataProvider{

&CustomersSDT = GetCustomers() // a DataProvider that Outputs Customers collectionCustomer Input &Customer in &CustomersSDT{

Id = &Customer.CodeName = &Customer.Name

}}

Similar ao ‘For &i=1 to 12’da linguagem procedural

Outro Input pode ser um SDT collection:

Similar ao ‘For &var in Expression’da linguagem procedural

Page 267: 93909254 GENEXUS Heuristica Apostila Teorica

267

Atualização da Base de Dados

Page 268: 93909254 GENEXUS Heuristica Apostila Teorica

268

• Atualização interativa: • Transações:

• Através do form o usuário ingressa/modifica/elimina os dados.

• Vantagens:

• As regras de negócio são executadas (e não se atualiza registro que viole regra Error especificada)

• Não se atualiza registro que viole integridade referencial.

• Business Components (BC)

• Atualização não interativa:• Business Components (BC)

• Procedures

Atualização BDInsert-Update-Delete

Até aqui somente conhecemos uma forma de atualizar a base de dados de nossa aplicação: as transações.Como sabemos, uma transação determina a ou as tabelas requeridas para armazenar sua informação. Por sua vez, ao ser gerada, se converte no programa que implementa a lógica de inserção, eliminação e modificação de dados nessas tabelas, de forma totalmente transparente para o programador. Também a transação permite definir todas as regras de negócio que os dados associados deverão cumprir. O programa gerado se encarrega de executá-las. Assim, se em uma transação temos uma ou várias regras Error, que se disparam ao satisfazer determinadas condições, essas regras estarão incluídas no código gerado, e não se permitirá atualizar a base de dados até as condições que disparam essas regras deixarem de satisfazer para os dados que estão manipulando nessa oportunidade.Assim mesmo, como vimos, as transações asseguram o controle de integridade referencial, muito importante para assegurar a consistência da base de dados.

Mas as transações não cobrem todas as necessidades referente a atualização de dados. Também seránecessário uma forma não interativa, batch, para realizar atualizações sobre as tabelas.

Para isso existem duas alternativas: atualização utilizando o que se conhece como Business Component, absolutamente relacionado com as transações, ou utilizar comandos específicos para tal fim dentro de objetos de tipo Procedure.

Depois veremos que os Business Components permitem grande flexibilidade, visto que permitem atualizar a base de dados de qualquer forma: tanto interativa como não interativa.

Em seguida introduziremos os Business Components e depois os comandos de atualização direta dentro dos Procedimentos.

Page 269: 93909254 GENEXUS Heuristica Apostila Teorica

269

Business ComponentsCenário

• Necessitamos registrar os recibos que efetuamos aos nossos clientes.

Regras:Default( BillDate, &today);Error( ‘The invoice period considered must be past’ ) if BillInvoicePeriodEndDate >= BillDate;Error( ‘Wrong invoice period’ ) if BillInvoicePeriodStartDate > BillInvoicePeriodEndDate;

Mas este é um caso que não nos serve a transação, visto que a geração de recibos é uma tarefa batch: se lança uma vez ao mês um processo que calcula e registra todos os recibos correspondentes as faturas dentro de determinado período.

autonumber

Page 270: 93909254 GENEXUS Heuristica Apostila Teorica

270

Business ComponentsCenário

Bill {

BillDate = &todayCustomerIdBillInvoicePeriodStartDate = &startBillInvoicePeriodEndDate = &endBillAmount = sum( InvoiceAmount, InvoiceDate >= &start and InvoiceDate <= &end and

InvoicePendingFlag )}

parm( in: &start, in: &end);Output: BillCollection: TrueCollection Name: Bills

• Já tínhamos declarado o Data Provider ‘GetBills’ que realizava o processo de geração de recibos desejado, mas não gravava:

E nos devolvia uma coleção de tipos de dados estruturados (SDT). Se observarmos, a estrutura hierárquica deste DP é quase idêntica a estrutura da transação Bill...

Page 271: 93909254 GENEXUS Heuristica Apostila Teorica

271

Business ComponentsCenário

• ...e se pudéssemos guardar em uma estrutura os dados e depois gravá-los na base de dados?

Bill

Bill

Bills

BillDate 12/12/08

CustomerId 2516

... ...

BillAmount 1000

BillDate 12/12/08

CustomerId 158

... ...

BillAmount 750

For &bill in GetBills( &start, &end )&bill.Save()

endfor

e além de gravar, executar as mesmas regras que se executam quando se grava mediante a transação Bill, e controlando além disso a integridade referencial?

&bill não será uma variável de tipo SDT, mas sim Business Component!

Page 272: 93909254 GENEXUS Heuristica Apostila Teorica

272

Business ComponentsBC

• A partir de uma transação, pode-se criar Business Component (BC).

Permite encapsular a lógica da transação (regras, eventos, controles de integridade referencial, estrutura dos dados) de tal forma que possa realizar inserções, modificações e eliminações sem necessidade do form...

É criado automaticamente na KB um tipo de dados Business Component, que pode ser associado a variáveis, e cujo nome será o da transação.

Por default a propriedade Business Component estará apagada. Isso significará que a lógica de negócio dada pela transação, somente será utilizada dentro da própria transação, e não ao se criar um tipo de dados com o mesmo nome da transação, Bill, que permita encapsular a lógica da transação para utilizá-la a partir de outros objetos.

Page 273: 93909254 GENEXUS Heuristica Apostila Teorica

273

Business Components

Em qualquer objeto GeneXus (ex: um procedimento):A variável &bill terá a mesma estrutura que o SDT obtido a partir da transação, e se trabalha de forma análoga, mas além disso oferece métodos para atualizar a base de dados em função desses valores.

&bill.BillInvoicePeriodStartDate = #10-10-08#&bill.BillInvoicePeriodEndDate = #09-10-08# &bill.Save()

Será inserido registro na tabela BILL?

Page 274: 93909254 GENEXUS Heuristica Apostila Teorica

274

Business ComponentsInsert

O que acontece na transação se tentássemos gravar com estes dados?

10/10/08 09/10/08>Não será inserido!

&bill.CustomerId = 3456&bill.BillInvoicePeriodStartDate = #10-10-08#&bill.BillInvoicePeriodEndDate = #09-10-08# &bill.Save()

Default( BillDate, &today);Error( ‘The invoice period considered must be past’ ) if BillInvoicePeriodEndDate > BillDate;Error( ‘Wrong invoice period’ ) if BillInvoicePeriodStartDate > BillInvoicePeriodEndDate;

Observe que se consideram alguns membros da estrutura da variável &bill, Business Component, e depois se executa o método Save (inexistente em SDTs).

Isto é equivalente ao que ocorria de forma interativa se o usuário final insere esses mesmos valores nos atributos correspondentes do form da transação, e depois pressionar o botão ‘Confirm’.

Portanto, da mesma forma que ocorre com a transação, deverão ser disparadas as regras e serem realizadas os controles de integridade referencial. O que acontecerá com esse conjunto de dados se tentar gravar mediante a transação? A gravação é impedida, devido que está cumprindo a condição da segunda regra de error. Por outro lado, se não existisse na tabela CUSTOMER um cliente com identificador 3456, a integridade referencial vai falhar e assim tampouco deixaria de ingressar o registro na tabela BILL da base de dados.

Page 275: 93909254 GENEXUS Heuristica Apostila Teorica

275

Business ComponentsInsert

&bill.CustomerId = 3456&bill.BillInvoicePeriodStartDate = #09-10-08#&bill.BillInvoicePeriodEndDate = #10-10-08# &bill.Save()

E agora que os dados não violam regras e supondo que o cliente 3456 existe e&today>10/10/08?

Será inserido registro na tabela BILL!

Com quais valores de BillId, BillDate e BillAmount?

BillId era autonumber...BillDate = &today... se dispara regra DefaultBillAmount vazio... não tem regra

e CustomerName?

Antes de executar o método Save do Business Component, o valor de BillId na estrutura de &bill será vazio. Portanto, uma vez que se execute o Save, como o atributo BillId era autonumber na tabela BILL, se executa a propriedade a nível da tabela e o registro será inserido com o número seguinte ao último dado.

No caso de BillDate, da mesma forma, como não se atribui valor na estrutura de &bill, antes do Save estarávazio, mas quando este se execute, será disparada a lógica da transação, e em particular a regra Default( BillDate, &today ) declarada. Portanto no registro inserido na base de dados, o valor do atributo BillDate

corresponderá a data de hoje.

Para BillAmount poderíamos fazer a mesma análise. Mas a diferença do caso anterior, não tem regra que atribui valor, pela qual se insere o registro com valor vazio neste atributo.

Se atribuir valor para &bill.CustomerName não será considerado na hora da inserção, visto que CustomerName é um atributo inferido, e não tem regra Update que permita modificá-lo.

O mesmo acontece para atributos definidos a nível da estrutura da transação mas que foram fórmulas. Isto é, são atributos virtuais na transação, e também são a nível do Business Component. Seu valor é disparado.

Page 276: 93909254 GENEXUS Heuristica Apostila Teorica

276

Business ComponentsUpdate-Delete

&bill.Load( 100 ) &bill.BillDate = #06-01-08#&bill.CustomerId = 1258 &bill.Save()

E se o desejado é atualizar um registro, não inserir um registro novo?

Se atualiza o registro 100 da tabela BILL!(sempre que exista cliente 1258 e06/01/08>=BillInvoicePeriodEndDate)

E para eliminar o recibo 100? &bill.Load( 100 ) &bill.Delete()

Se realiza sempre e quando não exista nenhuma tabela que referencie ao Bill 100!

Page 277: 93909254 GENEXUS Heuristica Apostila Teorica

277

enum

Business ComponentsGerência de erros

&bill.Load( 100 ) &bill.BillDate = #06-01-08#&bill.CustomerId = 1258 &bill.Save()

Em transações vemos os erros interativamente (e no Error Viewer).Como nos inteiramos dos erros ou mensagens resultantes ao tentar atualizar via BC?

Temos os métodosBooleanos:

&bill.Fail() &bill.Success()

E em caso de falha (por regra Error, falha de IR ou de duplicação) e/ou de regras Msg podemos obter a lista de mensagens de advertência ou de error:

&messages = &bill.GetMessages()

de tipo pré-definido SDT...

WarningError

Para gerenciar os erros terá que definir uma variável de tipo de dados SDT pré-definido (vem com a KB) Messages (collection).

Quando se executam os métodos: Save, Check, Load, Delete se disparam e carregam as mensagens gerados automaticamente por GeneXus assim como as regras Msg e Error definidos na transação. Se recomenda que sempre se recupere a lista destas mensagens e se faça uma “gerência de erros”.

As mensagens mais comuns geradas automaticamente por GeneXus são:

As regras Msg e Error aceitam em sua definição além do parâmetro com a mensagem a mostrar, um segundo parâmetro que define o Identificador da mensagem. O objetivo é que quando se execute a transação como Bussiness Component, e se obtenha a lista de mensagens ocorridas depois de executar uma ação sobre a base de dados, se tenha de cada mensagem, além da mensagem em si, seu identificador, sendo possível assim avaliar o identificador da mensagem para codificar o comportamento como conseqüência:

Msg|Error(<mensaje>, <Id do mensaje>)

Exemplos de <Id do mensaje>: "1", "2", "Error1", "Error2" ou uma descrição como ser "CustomerNameCannotBeEmpty", etc.

Se não especificar um identificador para a mensagem,, terá que perguntar pelo texto da mensagem.Nota: Para as mensagens geradas automaticamente por GeneXus, o Id é sempre em Inglês (independentemente do idioma selecionado no modelo).

Page 278: 93909254 GENEXUS Heuristica Apostila Teorica

278

Business ComponentsCaso de uso

Data Provider tem como output uma coleção de Business Component Bill!

Business Component omite valor da propriedade ‘Commit on Exit’ da transação:tem que utilizar comando Commit/Rollbackde forma explícita!

Necessitamos mudar para ‘False’ atributo InvoicePendingFlag de invoices faturados...

Aqui completaríamos o processo de geração de recibos.

Observemos primeiramente um fato importante: um data provider não somente pode devolver um SDT simples ou coleção, mas também um BC simples ou coleção.Importante: o BC devolvido somente poderá inserir na base de dados. Isto é, um Data Provider somente permite satisfazer sua estrutura, para depois fazer uma operação de INSERT sobre a base de dados. Não serápossível fazer uma atualização ou eliminação com um BC carregado via Data Provider.

Observe por outro lado como foi definido a variável &message de tipo de dados Messages.Message, correspondente a os itens do SDT pré-definido Messages devolvido pelo método GetMessages do BC.

Uma vez que obtemos e ingressamos na tabela BILL todos os recibos correspondentes ao faturamento, deveríamos percorrer as faturas consideradas, e modificar o valor de seu atributo InvoicePendingFlag, passando-o para False. Lembremos que o valor deste atributo se utiliza para não processar duas vezes uma mesma fatura. Lembremos que este valor se utiliza no Data Provider no cálculo do elemento BillAmount:

sum( InvoiceAmount, InvoiceDate >= &start and InvoiceDate <= &end and InvoicePendingFlag )

Deixaremos pendente esta última parte para quando estudarmos, umas páginas mais adiante, as formas de atualização direta, dentro de procedimentos exclusivamente, dos registros das tabelas.

Page 279: 93909254 GENEXUS Heuristica Apostila Teorica

279

Business ComponentsOutra opção

Este objeto é do tipo Web Panel. O utilizamos para pedir ao usuário final o período de faturamento

&StartDate

&EndDate

A partir de uma Web Panel também pode ser utilizado BC para atualizar a base de dados

Adiantamos aqui em apresentar outro tipo de objeto interativo que estudaremos um pouco mais adiante, a Web Panel, mostramos um objeto deste tipo em execução. Sua função será pedir ao usuário final um par de valores, que armazenem nas variáveis correspondentes de tipo Date (&startDate e &endDate) e depois, quando o usuário pressione o botão associado ao Evento Enter da Web Panel, se execute seu código.

Observe que o código é idêntico ao do procedimento visto antes. Com este exemplo pretendemos mostrar que mediante um Business Component pode se atualizar a base de dados a partir de qualquer objeto GeneXus.

Page 280: 93909254 GENEXUS Heuristica Apostila Teorica

280

Business ComponentsCaso de uso interativo

• Problema: inserir país somente se existir um cliente novo para o mesmo e não pode ficar país sem cliente no sistema.

commit automático

1

2

3

se o sistema cair aqui?

Lembremos que não se pode ter somente uma UTL com duas transações.Então?

4 commit automático

Vamos supor que cada vez que se insere um novo país no sistema, é necessariamente devido a que se tem um novo cliente desse país. Vamos supor que como requerimento, além disso, não deve ficar abaixo nenhuma circunstância ingressado um país sem pelo menos um cliente associado.

Tal como temos implementada a aplicação, isto não se está controlando. Como se insere um país e um cliente para o mesmo? O usuário deve executar a transação Country, ingressar o país. Depois abrir a transação Customer, e ingressar os dados do cliente e confirmar. Mas o que acontece se cair o sistema quando se estáingressando o cliente? Ficará o país ingressado (lembrar que cada transação por default faz commit ao final).

Page 281: 93909254 GENEXUS Heuristica Apostila Teorica

281

Business ComponentsCaso de uso interativo

• Solução: na transação Country, criar variável &customer de tipo BC Customer e inseri-la no Form e agregar a regra Accept.

Commit automático

&customer.CountryId = CountryIdon AfterInsert;

&customer.Save() on AfterInsert;msg( ‘It fails’) if &customer.Fail()

on AfterInsert;

1 2

3

Desvantagem: não são disparadas de forma interativa as regras associadas a Customer...

Necessitamos que a inserção do país na tabela COUNTRY e a inserção do cliente na tabela CUSTOMER se realizam dentro de uma mesma UTL. Como temos visto, as operações efetuadas por 2 transações não podem ser incluídas numa única UTL. Por esta razão, necessitaremos fazer a inserção dentro da mesma transação.Como? Dentro da transação Country, definimos uma variável &customer, de tipo business component Customer (para isso, teremos previamente que ter setado a propriedade Business Component da transação Customer, de tal maneira que se crie este tipo de dados na KB). Umaa vez efetuado isto, simplesmente inserindo no form a variável (da mesma forma que acontecia com um SDT), GeneXus colocará controles para cada um dos membros da estrutura: &customer.CustomerId, &customer.CustomerName, &customer.CustomerAddress, etc.

As variáveis por default nas transações são de saída, terá que especificar regra Accept para que possam ser escritas em execução e o possa ingressar valores para as mesmas.

O Save do customer deverá realizar-se necessariamente depois de inserir o país em sua tabela (do contrário a integridade referencial falha). Portanto nas regras:

&customer.Save() on AfterInsert;

Sabemos que neste momento o registro correspondente ao país já terá sido gravado, e depois neste Save... na continuação, o commit automático.

Page 282: 93909254 GENEXUS Heuristica Apostila Teorica

282

Business ComponentsResumo

• Objetivo: • Reutilizar a lógica do negócio definida nas transações. Usar o poder das

transações (sem seus forms) desde outros objetos GeneXus:

• Procedimentos, Web Panels...

• A partir de outra Transação (da mesma forma que uma variável podia de forma interativa inseri-la no Form, também um BC)

• Benefícios: • Atualização na BD garantindo integridade dos dados e execução das

regras do negócio.

• Reutilização de código (as regras de negócio não precisam ser duplicadas)

• Vários objetos GeneXus podem atualizar a BD.

Page 283: 93909254 GENEXUS Heuristica Apostila Teorica

283

Business ComponentsRegras e Eventos

• Regras: são executadas todas as regras da transação exceto (são ignoradas pelo especificador):

• as que incluem user interface ( Ex: Customer.call())

• as que não aplicam: parm, prompt, NoPrompt, Default_mode, etc

• Eventos: todos os eventos da transação são ignorados, exceto os eventos Start e After TRN (e eles também são ignorados se incluírem referências a objetos com user interface).

Nota: quando falamos “são ignorados” nos referimos no contexto da atualização utilizando BC, não quando a atualização é realizada através da própria transação.

Se existe uma regra que chama um objeto que possui interface, isto é, form, essa regra não é incluída no BC. Existe uma forma de especificar que uma regra declarada na transação não seja aplicada quando se executa a transação, mas somente quando se executa o Business Component associado: é qualificando a regra com [BC].

Exemplo:

[BC] Default( BillDate, &today);

Se quiser qualificar de uma só vez um conjunto de regras:

[BC]{

regra1;regra2;...regran;

}

O mesmo vale para eventos.

Analogicamente, existem qualificadores para indicar que uma regra somente se execute se estiver correndo a transação com seu form web: [WEB].

Page 284: 93909254 GENEXUS Heuristica Apostila Teorica

284

Atualização não interativa direta

Procedimentos

Page 285: 93909254 GENEXUS Heuristica Apostila Teorica

285

ProcedimentosUpdate

• Não tem um comando específico para modificar um registro: se realiza de forma implícita dentro do comando For each.

Exemplo:

parm( in: CustomerId, in: &StartDate, in: &EndDate);

A modificação de dados da base de dados se realiza em forma implícita: não tem um comando específico de atualização.

Para atualizar um ou vários atributos de uma tabela se utiliza o comando For each, e dentro do mesmo o comando de atribuição

Podem ser realizadas várias atualizações dentro do mesmo For each, podendo estes pertencer tanto a própria tabela base como a tabela estendida.

O exemplo que apresentamos completa o que havíamos iniciado a respeito ao processo de geração de recibos.

Observe que aqui se está percorrendo a tabela INVOICE, filtrando por InvoiceDate, por InvoicePendingFlag, assim como por CustomerId (na listagem de navegação se observa que mesmo não tendo sido especificado order, ao receber no atributo CustomerId, que é foreing key, se ordena por este atributo para otimizar). Dentro do for each, para cada fatura que cumpre as condições, se atualiza o valor do atributo InvoicePendingFlag. Aqui poderiam atualizar-se não somente esse atributo, mas qualquer da própria tabela INVOICE, ou de sua estendida, com as exceções indicadas na continuação.

Page 286: 93909254 GENEXUS Heuristica Apostila Teorica

286

ProcedimentosUpdate

• Atributos atualizáveis: os da tabela estendida do For each. Exceto:

• os que formam parte da chave primária da tabela base.

• os que formam parte do índice pelo qual se está acessando a tabela.

• A atualização se realiza no Endfor.

• A integridade referencial não é controlada. • Se atualizar um atributo que é FK � não se controla existência.

• Somente se realiza controle de duplicados: For each ...bloque1

[when duplicatebloque2...]

Endfor

Se dentro do for each tentar atualizar um atributo que tem definido um índice unique, e existe o valor duplicado, não se atualiza... existindo a cláusula when duplicate seu código é executado.

Vamos supor que temos o seguinte diagrama de Bachman genérico:

E no Source de um procedimento fazemos:For each

C = &CE = &E

D = &DEndfor

Aqui a tabela base do For each será claramente a de chave primária A e dentro do For each estamos atualizando tanto atributos da própria tabela base como da estendida. Em que momento ocorre efetivamente a atualização dos registros envolvidos?A atualização não ocorre quando encontra um comando de atribuição dentro do For each, mas sim depois que se encontram todos, para cada instancia da tabela base, isto é,quando se chega ao Endfor para cada iteração.

Como vimos antes, não podemos atualizar dentro do comando For each atributos da chave primária. Todavia poderíamos querer atualizar um atributo que não está definido como chave primária, estádefinido como chave candidata (mediante um índice unique). Se o atributo é chave candidata, deve controlar-se que não se dupliquem seus valores, caso encontre duplicado, não permite fazer a atualização.Se desejar tomar uma ação no caso disso ocorrer, o comando For each agrega a cláusula when duplicate. Somente tem sentido se existe alguma chave candidata para esse For each.

A*BCD

B*

EF

Page 287: 93909254 GENEXUS Heuristica Apostila Teorica

287

ProcedimentosUpdate

• Eficiência:

• Atualização massiva: cláusula Blocking reduz número de acessos a BD.

for eachwhere InvoiceDate >= &StartDatewhere InvoiceDate <= &EndDate

InvoicePendingFlag = Falseendfor

Se tiver um milhão de registros para serem atualizados?

Para cada um se envia um comando UPDATE ao servidor de BD (que não tem por que estar na mesma máquina que o Web Server) � eficiência?

for eachwhere InvoiceDate >= &StartDatewhere InvoiceDate <= &EndDateBlocking 1000

InvoicePendingFlag = Falseendfor

Até a N-ésima (1000) iteração, o Update se realiza em um buffer. Com a N-ésima se envia comando: Update massivo na BD e se atualizam os dados do buffer.

Realizar um “blocking” nas operações de atualização da BD significa armazená-las em memória e enviá-las em grupo ao DBMS. Ao invés de interagir com o DBMS em cada operação de atualização, a interação tem lugar somente cada N operações de atualização, onde N é o número que se estabelece na cláusula Blocking.

Não será o caso de nosso exemplo, mas o que aconteceria se estiver fazendo uma atualização massiva que inclui algum atributo chave candidata da tabela, e se encontram duplicados para alguns dos registros do grupo de 1000 que se está processando?

Nesse caso, uma vez chegado o buffer com as 1000 atualizações, ao enviar ao BD o comando UPDATE do grupo, saltará o error de duplicados e se iterará sobre o grupo, realizando um comando UPDATE individual de BD, um por um.

Page 288: 93909254 GENEXUS Heuristica Apostila Teorica

288

ProcedimentosDelete

• Para eliminar registros de uma tabela: Comando Delete.

• Deve ir dentro de um For each.

• Elimina o registro da tabela base em que estiver posicionado.

• Se executa assim que encontra o comando (e não no Endfor).

• Não controla a Integridade ReferencialExemplo:

For eachdefined by InvoiceDateBlocking 1000

DeleteEndfor

Elimina todos os registros da tabela base: INVOICE, eliminando-os em grupos de 1000 (para fazê-lo de forma mais eficiente).

Para eliminar dados se utiliza o comando Delete dentro do comando For each.

O comando Delete elimina o registro que estiver posicionado no momento dado. É por isso, que não pode aparecer “solto” dentro do Source. Deve estar dentro de um comando For each, cuja tabela base seja a tabela que se quer eliminar registros. Somente se eliminam os registros da tabela base, não da estendida.

Sei desejamos eliminar todas as faturas anteriores a uma data informada, podemos programar um procedimento:

For eachwhere InvoiceDate <=&date

For eachdefined by InvoiceDetailQuantity

DELETE // se eliminam as linhasEndforDELETE //depois de eliminar as linhas se elimina o cabeçalho

Endfor

Para uma eliminação mais eficiente, dependendo do número de registros da base de dados, convêm agregar cláusula Blocking com um fator de bloqueo, N, adequado. Por exemplo, se agregar “Blocking 1000” a eliminação física não é realizada em cada iteração, mas sim a cada 1000 vezes que se chegue ao Endfor, se eliminarão o grupo de 1000 registros em um único acesso a Base de Dados (ao invés de 1000).

Page 289: 93909254 GENEXUS Heuristica Apostila Teorica

289

ProcedimentosInsert

• Comando New: permite inserir um registro em uma tabela.

• Realiza o controle de duplicados:

NewProductId = &ProductId

ProductPriceListDate = &todayProductPriceListPrice = &price

endnew

Procedimento “NewPrice”

NewProductId = &ProductId

ProductPriceListDate = &today

ProductPriceListPrice = &price

when duplicatefor each

ProductPriceListPrice = &priceendfor

endnew

Se já existe o registro para o produto e data? � atualizar o preço: cláusula when duplicate.

Vamos supor que queremos implementar um procedimento que faça o seguinte: para o produto cujo código é recebido por parâmetro, insere um novo preço (também recebido por parâmetro) em sua lista de preços, para a data correspondente ao dia em que se executa o procedimento. Este deve criar um novo registro na tabela PRODUCTPRICELIST, que está composta pelos atributos ProductId, ProductPriceListDate e ProductPriceListPrice, sendo sua chave primária composta, conformada por ProductId e ProductPriceListDate.

Para isso se utiliza o comando new que escrevemos acima. Observemos que dentro do mesmo aparecem comandos de atribuição, onde se dá valor aos atributos da tabela que se quer inserir o registro.

Cada vez que GeneXus encontra um new, deve determinar a tabela na qual se realizará a inserção (tabela base do new). É determinada a partir dos atributos que aparecem dentro do comando new, do lado esquerdo numa atribuição.

O único controle que realiza, é o de duplicados. Em nosso caso, se existir um registro com os valores de ProductId e ProductPriceListDate, não se realizará a inserção. Se programar a cláusula when duplicate, se atualiza o registro encontrado.

Observemos que para realizar a atualização do atributo, a atribuição deve estar dentro de um comando For each. Se não colocamos o For each não se realizará a atualização do preço para esse registro, isto é, é como se não tivesse incluído cláusula when duplicate.

Se quiser inserir um registro para o qual exista chave candidata duplicada, também se controla e não se realizará a inserção. Em caso de existir cláusula when duplicate, se executa.

Page 290: 93909254 GENEXUS Heuristica Apostila Teorica

290

ProcedimentosInsert

• Exemplo: se quisermos realizar a geração de recibos diretamente em um procedimento (não através de BC).

No for each se percorrem os clientes ativos e o new insere na tabela BILL um recibo novo para esse cliente(por que CustomerId não aparece atribuído?).

Se são milhares de clientes, pode otimizar a inserção e fazer em blocos

For each using ActiveCustomers()NewBlocking 1000

BillDate = &TodayBillInvoicePeriodStartDate = &startBillInvoicePeriodEndDate = &endBillAmount = sum( InvoiceAmount, InvoiceDate >= &start and

InvoiceDate <= &end and InvoicePendingFlag )

Endnewendfor

O caso mais comum será ter o comando new dentro de um for each, visto quem em geral se quer inserir registros na base e cálculos efetuados em função de outros.

O mesmo processo de geração de recibos que havíamos resolvido anteriormente utilizando Data Provider e Business Component, poderíamos realizá-lo com um procedimento que utilize o comando new de inserção. Qual alternativa você escolheria? Lembre que com os comandos de atualização dentro de procedimentos, o único controle que será realizado é o de duplicados.

Se as inserções são muitas, assim como vimos para o caso das atualizações, dispomos da cláusula blocking para ir guardando em um buffer e depois fazer a inserção de todos os registros uma vez.

Em nosso caso não falhará a inserção, devido que a chave primária é autonumber, e que não temos chaves candidatas (através de índices unique) na tabela de recibos (BILL).

Mas se não for o caso, como as inserções vão sendo realizadas no buffer até chegar a 1000, não épossível até completar o buffer saber se alguma operação falhará. Quando se executa o INSERT massivo da base de dados, ali se pode falhar alguma inserção. Nesse caso, se itera nos elementos do buffer, executando o INSERT simples, um por um. Se existe cláusula When duplicate no New, então pelos registros que falhem, se executa a cláusula.

Page 291: 93909254 GENEXUS Heuristica Apostila Teorica

291

ProcedimentosInsert

• Sintaxe do new

devempertencer a uma tabela física �

tabela base

Nota: Não é necessário atribuir valor a todos e cada um dos atributos da tabela. Alguns vem instanciados pelo contexto do new (ex: se está dentro de um for each), não é necessário atribuir valor para o registro a ser inserido (pegam do contexto).

new[ Defined by att1,…, attN ][ Blocking NumericExpression ]

bloque_asignaciones1

[ when duplicateFor each

bloque_asignaciones2

Endfor ]endnew

att1,…, attN

attx1 = ......attxm = ...

Na sintaxe apresentada, bloque_asignaciones1 é um bloque de código composto na sua maioria por sucessivos comandos de atribuição (aqui se atribui valor aos atributos da tabela na que vai inserir o registro, podem também atribuir-se valores a variáveis).

A cláusula Defined By opcional, se incorpora os mesmos efeitos que no comando For each: ajudar a determinar a tabela base.

A tabela base do new se obtêm dos atributos do Defined By e os que apareçam do lado esquerdo de atribuições dentro do bloque_asignaciones1. Aqui não se utiliza a tabela estendida.

No caso de que o comando new esteja dentro de uma cláusula repetitiva (ex. For each), é possível reduzir o número de acessos a base de dados usando a cláusula blocking.

O comando new realiza um controle de duplicados, de tal maneira que não se permite inserir um registro que já exista na tabela.

A cláusula when duplicate do comando permite programar a ação em caso de que o registro jáexista na tabela base (tanto por chave primária como por chave candidata).

Normalmente, ao ocorrer o que acabamos de falar, se quer atualizar alguns dos atributos de dito registro. Para isso, em bloque_asignaciones2 se realizam tais atribuições, mas como o que se faz éatualizar um registro (e não inserir um novo), estas atribuições aparecem entre “For each – Endfor”, como vimos, as atualizações somente podem ser realizadas dentro de um For each.

Se a cláusula when duplicate para um new não for especificada, se o registro que se quer inserir se encontra duplicado não se realizará nenhuma ação e a execução continuará no comando seguinte. Isto é, como não pode inserir o registro porque já existe um, não faz nada e segue adiante com o próximo comando.

Page 292: 93909254 GENEXUS Heuristica Apostila Teorica

292

Atualização BDBC versus Proc

• Atualização via Business Component:• Se realizam controles de integridade referencial.

• Se controlam duplicados.

• Se disparam as regras do negócio.

• Atualização via comandos em procedimentos:• Não se realiza controle de integridade referencial.

• O único controle que se realiza é o de duplicados.

• Não tem nenhuma relação com transação � aqui não tem regras.

-

+

Nos procedimentos o único controle de integridade que se realiza automaticamente é o controle de duplicados. O controle de integridade referencial fica por conta do programador, o que não ocorre nas transações (em um Business Component).

Fica claro da numeração mostrada acima que os Business Components oferecem todas as garantias e constituirão a forma de atualização privilegiada.

Cabe perguntar-se então: quando atualizar utilizando estes comandos? A resposta é: quando a performance for um problema.

Um exemplo discutível é o que utilizamos para alterar o valor do atributo InvoicePendingFlag a False. Não havia nenhuma regra que o implicara, não envolvia integridade referencial, nem duplicados e podia envolver milhares de registros. Qual seria a alternativa? Prender a propriedade Business Component da transação Invoice, e no procedimento MarkInvoiceAsNotPending definir variável &invoice com esse tipo de dados e depois:

for eachwhere InvoiceDate >= &startDatewhere InvoiceDate <= &endDatewhere InvoicePendingFlag

&invoice.Load ( InvoiceId)&invoice.InvoicePendingFlag = False&invoice.Save()

endfor

Mas esta solução será mais ineficiente que a atualização direta utilizando “blocking factor”, sabendo que milhares de faturas deverão ser atualizadas.

Page 293: 93909254 GENEXUS Heuristica Apostila Teorica

293

Uso de Subtipos

Page 294: 93909254 GENEXUS Heuristica Apostila Teorica

294

• GeneXus estabelece as relações através de seus nomes.

• Mediante subtipos se pode estabelecer que dois atributos com nomes diferentes correspondem ao mesmo conceito.

• Casos de subtipos:• A. Múltiplas referências

• B. Especialização de um nível (relação 1-1)

• C. Subtipos recursivos

Definição de subtipos

Page 295: 93909254 GENEXUS Heuristica Apostila Teorica

295

{CityId *CityName

}

• Atributos conceitualmente iguais que cumprem regras diferentes(ex.: reservas de passagens).

A. Múltiplas referências

City{ReservationId*CityIdCityId

}

Reservation

{CityId *CityName

}

origemdestino

PROBLEMAAtributos com

o mesmo nome

SOLUÇÃO

City{

ReservationId*ReservationCityFromIdReservationCityToId

}

Reservation

Desapareceo problema!

subtipo

subtipo

Realidade para representar/desenhar: Em cada reserva tem duas cidades envolvidas, as quais cumprem regras diferentes. O rol de uma das cidades é o de ser a “cidade de partida” (cidade origem) e o rol da outra é o de “cidade de chegada” (cidade destino).O domínio de ambas cidades é o mesmo, o da tabela CITY.

A forma de representar tanto a “origem” como o “destino” são cidades da tabela CITY, é desenhando a transação “Reservation” na forma mencionada inicialmente na transparência. Todavia, não épossível que na estrutura de uma transação figure o mesmo atributo mais de uma vez, pois não teria maneira de identifica-los.SOLUÇÃO: chamar as duas cidades de reserva com diferentes nomes de atributos. Qualquer das seguintes opções é válida. Escolhemos a 3era por maior clareza.

Opção 1) ReservationCityFromId cidade origemCityId cidade destino (mesmo nome que a PK de CITY)

Opção 2) CityId cidade origem (mesmo nome que a PK de CITY)ReservationCityToId cidade destino

Opção 3) ReservationCityFromId cidade origemReservationCityToId cidade destino

O problema é que ao colocar por exemplo ReservationCityFromId ao invés de CityId, GeneXus deixa de inferir que ReservationCityFromId corresponde ao código de uma cidade da tabela de CITY. Como fazemos para relacioná-los, sendo que tem nomes de atributos diferentes? ver resposta na próxima folha …

Page 296: 93909254 GENEXUS Heuristica Apostila Teorica

296

Para estes casos GeneXus fornece os SUBTIPOS, que permitem definir que dois atributos que se chamam diferentes correspondem ao mesmo conceito.

Em nosso exemplo, se definimos o atributo ReservationCityFromId como subtipo de CityId, estamos especificando que mesmo ReservationCityFromId e CityId são diferentes atributos (de nomes diferentes), correspondem, ao mesmo conceito (uma cidade da tabela CITY).

Ao estabelecer que um atributo é subtipo de outro, estamos estabelecendo uma dependência funcional entre eles.

Se ReservationCityFromId é subtipo de CityId, então dizemos que CityId é supertipo de ReservationCityFromId.

�Os atributos que se encontrem numa relação subtipo-supertipo compartilham a mesma definição (tipo de dados).

�Se realizam os controles de integridade referencial automaticamente.

�A tabela estendida obtida com a definição do subtipo, é a mesma que se obteria utilizando diretamente o supertipo.

Page 297: 93909254 GENEXUS Heuristica Apostila Teorica

297

• Com a definição dos subtipos antes mencionados:• Se estabelecem as seguintes relações:

• Os controles de Integridade Referencial (IR) são feitos automaticamente entre ambas tabelas quando utilizam suas correspondentes transações.

• Os atributos secundários de CITY:Pertencem a tabela estendida de RESERVATION, mas como existe dupla referência não se podem utilizar diretamente a partir de RESERVATION (ambigüidade de caminhos e com valores de cidades diferentes).

Solução � definir também subtipos para os atributos secundários de CITY, e incluí-los em cada um dos grupos de subtipos.

RESERVATION CITYReservationCityFromId

ReservationCityToId

A. Múltiplas referências

IMPORTANTE:Observe que este caso de múltiplas referências pode acontecer:

• na tabela base (*)• como na tabela estendida

(*) é o caso do exemplo, na mesma tabela (RESERVATION) tem mais de uma referência à outra tabela (CITY) e com valores diferentes.

RESUMINDO:sempre que a partir de uma tabela se acesse a outra que está em sua tabela estendida por “mais de um caminho” e com “valores diferentes”, é necessário definir SUBTIPOS, para que os atributos possam ser chamados de forma diferente e realizando todos os controles de integridade referencial.Uma vez definidos os grupos de subtipos que são necessários, a forma de indicar ao GeneXus qual os caminhos deve tomar para acessar a tabela destino, é mencionando os nomes de atributos correspondentes. Ex.: mencionar ReservationCityFromName caso queira nesse momento o nome da cidade origem, o ReservationCityToName caso queira o nome da cidade destino.

Page 298: 93909254 GENEXUS Heuristica Apostila Teorica

298

A. Múltiplas referências

{ReservationId*ReservationCityFromIdReservationCityFromNameReservationCityToIdReservationCityToName

}

Transação “Reservation” Tabela “Reservation”{

ReservationId*ReservationCityFromIdReservationCityToId

}FKFK

Nome de cada grupo de subtipos.

Inferido

Inferido

Com o grupo estamos indicando que os atributos pertencentes ao mesmo grupo de subtipos, estão relacionados. Por exemplo, no nosso exemplo, GeneXus saberá que o atributo ReservationCityToName será inferido através do atributo ReservationCityToId (e não através do ReservationCityFromId). Isto é por ambos pertencerem ao mesmo grupo (ao nome ReservationCityTo). Quando o usuário digita um valor sobre ReservationCityToId, não somente é feito de forma automática o controle de integridade referencial (que exista uma cidade com esse código na tabela CITY), e sim que vai inferir em ReservationCityToName o nome correspondente a esse código de cidade.

IMPORTANTE: Todo grupo de subtipos, deve conter um atributo ou um conjunto de atributos, cujos supertipos, juntos, correspondam a chave primária de uma tabela do modelo. Os demais atributos do grupo deveram ser do tipo “Inferred”, ou seja, poderão ser inferidos através da chave. Caso contrário o grupo estará mal definido.

Page 299: 93909254 GENEXUS Heuristica Apostila Teorica

299

SALE COUNTRY

CUSTOMER

SELLER

Um caminho a partir de SALE a COUNTRY: através do País do cliente (CountryId)

Outro caminho a partir de SALE a COUNTRY: através do País do vendedor (CountryId)

• COUNTRY pertence a tabela estendida de SALE por caminhos diferentes e com códigos de país diferentes.

Que país imprime? Quais dos caminhos toma?Tem uma ambigüidade no modelo de dados!

Layout:

A. Múltiplas referências a tabela estendida

Source:

Se desejarmos, por exemplo listar as vendas (SALE), e de cada uma delas mostrar os dados do cliente (nome, país, etc.) e do vendedor (nome, país, etc.):

• necessitamos um For Each com tabela base SALE e acessar através de sua extensão as tabelas CUSTOMER, SELLER e COUNTRY para listar os atributos secundários do cliente, vendedor e país respectivamente.

Problema:Os atributos de nome CountryId, CountryName e todos da tabela estendida COUNTRY pertencem à tabela estendida SALE por dois caminhos diferentes:

1) através do país do cliente e 2) através do país do vendedor.

Solução:Devemos diferenciá-los, chamá-los com diferente nome de atributo, mas querendo que continuem representando todas as relações e fazendo automaticamente todos os controles de integridade referencial.

Page 300: 93909254 GENEXUS Heuristica Apostila Teorica

300

SALE COUNTRY

CUSTOMER

SELLER

Quando queremos o país do cliente da venda: SaleCustomerCountryName

Quando queremos o país do vendedor da venda: SaleSellerCustomerName

SaleCus

tomerId

SaleSellerId

A. Múltiplas referências a tabela estendida

Solução

Uma vez definidos os dois grupos de subtipos que se mostram na figura, e fazendo a mudança correspondente na estrutura da transação Sale, resolve a ambigüidade no modelo de dados!

Page 301: 93909254 GENEXUS Heuristica Apostila Teorica

301

SaleCustomerCountryId SaleSellerCountryId

Problema resolvido!

A. Múltiplas referências a tabela estendida: Solução

Uma vez definidos os subtipos, temos que lembrar de usar o nome do atributo que corresponda ao que queremos acessar. Por exemplo, em todos aqueles objetos GeneXus nos quais gostaríamos de acessar ao código do nome do país do cliente da venda devemos usar atributos SaleCustomerCountryId e SaleCustomerCountryName respectivamente.

Page 302: 93909254 GENEXUS Heuristica Apostila Teorica

302

B. Especialização de atributos

PERSON

TEACHER STUDENT

Ex.: Sistema para uma Universidade …

Sistema Teachers

dados comuns a professorese estudantes

dados próprios dos estudantes

dados próprios dos professores

Sistema Students

Caso de subtipos “Especialização de atributos”:Quando se está modelando uma categorização. Geralmente é utilizada, quando um objeto do negócio compartilha todas as características de outro objeto, mas agrega mais algumas. A diferença pode estar tanto nas propriedades, como no seu comportamento.

Exemplo “Sistema para uma Universidade”:

Neste exemplo, o professor e o aluno possuem regras e comportamentos claramente diferenciados. Por exemplo, o professor terá cursos atribuídos, remuneração, etc. O aluno estaráinscrito num curso, terá pagamentos, assistência, escolaridade, etc.

Estamos em um caso que as regras e o tratamento das entidades da categorização estão claramente diferenciados.

Tanto os estudantes como os docentes compartilham informação em comum (ambos tem um nome, endereço, etc) mas também possuem informação diferente, que é própria de cada um.

Para representar esta realidade, são criadas três transações: “Person”, “Teacher” e “Student”.

Na transação “Person” figura a informação em comum. Para representar que tanto os estudantes como os docentes são pessoas, são utilizados subtipos.

Definindo que o identificador de “Teacher” é subtipo do identificador de “Person” estamos estabelecendo esta relação.

Cada vez que inserir um registro na tabela TEACHER através de sua transação, a checagem da integridade referencial é realizada contra “Person”. Da mesma forma, ao tentar eliminar um registro de “Person”, primeiro é verificado que não exista nenhum registro na tabela TEACHER (nem em STUDENT) com o mesmo valor na chave primária.

Page 303: 93909254 GENEXUS Heuristica Apostila Teorica

303

B. Especialização de atributos

“Person” “Teacher” “Student”{

PersonId*PersonNamePersonAddress

}

{TeacherId*TeacherNameTeacherAddressTeacherSalary

}

{StudentId*StudentNameStudentAddressStudentAverage

}

• São criadas 3 tabelas físicas.• São realizadas as checagens de IR contra a tabela PERSON.

A transação “Teacher” tem associada uma tabela que conterá fisicamente somente dois atributos: TeacherId e TeacherSalary.

TeacherId é o identificador da transação, será a chave primária da tabela associada. Alem disso, ao ser um subtipo de PersonId, será uma chave estrangeira da tabela PERSON. Portanto, serão realizadas as checagens de integridade referencial correspondentes.

Os atributos TeacherName e TeacherAddress são subtipos de PersonName e de PersonAddressrespectivamente e estão agrupados com TeacherId, que serão inferidos da tabela PERSON, através da chave estrangeira TeacherId (não estão armazenados na tabela TEACHER).

Page 304: 93909254 GENEXUS Heuristica Apostila Teorica

304

• Exemplo: Employee-Manager

Error(‘Deve ingressar um gerente para o empregado’) if not EmployeeIsManagerFlag and EmployeeManagerId.isnull();

Tabela EMPLOYEE

{EmployeeId*EmployeeNameEmployeeIsManagerFlagEmployeeManagerId

} FK

C. Subtipos recursivos

É possível ter uma tabela subordinada a si mesma utilizando subtipos.

Este tipo de subtipos se utiliza para modelar as relações recursivas. Por exemplo, a relação entre Empregado e Gerente: - cada empregado tem um gerente. Um gerente, a sua vez, é um empregado (aqui esta a recursividade).- um gerente pode ter vários empregados.

Além disso, a realidade a ser representada é que “somente os empregados que não são gerentes possuem um gerente”, então, ao inserir os dados tem que realizar os seguintes controles:-quando informar os gerentes, tem que permitir deixar nulo o atributo EmployeeManagerId. Para isto, trocamos para ‘Yes’ a coluna Nulls do atributo EmployeeManagerId, que é uma FK na tabela EMPLOYEE.-que todo empregado que não é gerente, tenha um gerente. Este controle é realizado com a regra error mostrada na figura.

O atributo EmployeeManagerName não fica armazenado na tabela EMPLOYEE, é inferido após ingressar um valor em EmployeeManagerId.

Por ser EmployeeManagerId subtipo de EmployeeId, são realizadas automaticamente os controles de integridade referencial da tabela com ela própria. Isto pode ser visto na navegação da transação na página seguinte.

Page 305: 93909254 GENEXUS Heuristica Apostila Teorica

305

• Listagem de navegação detalhada:

C. Subtipos recursivos

Page 306: 93909254 GENEXUS Heuristica Apostila Teorica

306

• Quando se define um subtipo este "herda" a definição do supertipo.

• Pelo menos um dos supertipos do grupo (ou conjunto de supertipos do grupo) deve(m) corresponder a PK de uma tabela do modelo.

Considerações

Page 307: 93909254 GENEXUS Heuristica Apostila Teorica

PATTERNS

307

Page 308: 93909254 GENEXUS Heuristica Apostila Teorica

Patterns: Cenário

Filtro sobre osdados

Paginação

Tendo a transação Country e a transação Customer, queremos ter a aplicação mais vistosa, com consultas com vistas mais completas e com algum aumento de produtividade.

Por exemplo, trabalhar com os países de uma forma mais vistosa e amigável que a que brinda somente a transação. Visualizar num grid os países existentes, com a possibilidade de filtrar por nome de país, e fixando a paginação ao grid, de tal forma que mostre um número fixo de registros por página...

Page 309: 93909254 GENEXUS Heuristica Apostila Teorica

Patterns: Cenário

New Country

Update Country

Delete Country

Transaction

...assim como poder ingressar um novo país (mediante a transação Country), ou selecionar um dos mostrados no grid, para poder modificá-lo ou eliminá-lo...

Page 310: 93909254 GENEXUS Heuristica Apostila Teorica

Patterns: Cenário

...ou incluso ver a informação completa desse país, incluindo os clientes associados...

Page 311: 93909254 GENEXUS Heuristica Apostila Teorica

Definição Padrões que podem ser aplicados a uma KB para implementar automaticamente certa funcionalidade.

Patterns

Padrões disponíveis:

• Work With• Category Seletores dentro das

Transações

Generalidades

� Uma vez aplicado o padrão, todos os objetos gerados ficam como parte da Base de Conhecimento.

É natural ao desenvolver, ter que resolver partes muito similares mas não exatamente iguais.

Por exemplo, se em uma Base de Conhecimento tem modelados os objetos da realidade Customer e Country, apesar de ditos objetos serem bem diferentes, os “Work With Customers” e “Work With Countries”respectivamente, possuem muitas coisas em comum: um grid no form, um conjunto de variáveis para utilizar em filtros, opções de ordens da consulta, chamadas à transação correspondente para atualizar a base de dados, etc..

Surgem então os Patterns, oferecendo a possibilidade de aplicar um padrão (pattern) às instâncias desejadas de uma Base de Conhecimento, e gerar todos os objetos GeneXus necessários para implementar certa funcionalidade, considerando seus dados específicos.

Seguindo com o exemplo mencionado inicialmente, é possível aplicar o padrão “Work With” na Base de Conhecimento, de tal forma que partindo das transações “Customer” e “Country” (e caso se deseja outras), se obtenha todo o desenvolvimento correspondente ao “Work With Customers” e “Work With Countries” para ambiente web (telas vistosas que implementam as consultas, com ordens, filtros, chamadas às transações correspondentes, e mais).

Page 312: 93909254 GENEXUS Heuristica Apostila Teorica

PatternsWork With

Gera a partir de uma Transação

� Tela Work With: consulta interativa, múltiplas ordens, filtros, chamada a transação. Etc.� Tela View: Registro selecionado, com a informação associada.

Transação

View

Work With

A tela Work With oferece:• Consulta interativa• Múltiplas ordens• Filtros• Chamada à Transação nos diferentes modos (insert, update, delete, display)• Possibilidade de incluir chamadas próprias a objetos• Link em cada linha do grid a tela ‘View’

A tela View mostra:• A informação do registro selecionado no grid Work With• Um tab control com:

• Um tab com a informação do registro• Um tab para cada tabela subordinada a tabela base do registro no grid Work With.:

Page 313: 93909254 GENEXUS Heuristica Apostila Teorica

PatternsAplicação

� Abrir a Transação

� Selecionar o padrão a ser aplicado (aparecerá a instância por default)

� Marcar a opção “Apply this pattern on save”

� Salvar a Transação

Para aplicar o pattern sem demoras, basta editar a instância (selector “Work With” da transação), marcar o check box e gravar. Pronto! Com isso são criados automaticamente os objetos GeneXus que implementam o pattern (em particular a tela de seleção e filtro e a tela de View que mostramos antes). Assim mesmo se modificará a transação para que agora receba por parâmetro o modo (Insert, Update, Delete, Display) e o país.

Page 314: 93909254 GENEXUS Heuristica Apostila Teorica

314

PatternsWork With: objetos gerados

Consequencia: São gerados na KB os objetos que já vimos em execução. Onde? No Folder View, abaixo da própria transação:

Uma vez gravada a instância, no folder view, abaixo o nome da transação, aparece o nome do pattern aplicado a mesma (em nosso exemplo WorkWithCountry) e todos os objetos que GeneXus deve criar para implementar.

Em nosso caso serão criados 2 objetos de tipo Web Component, e 2 objetos de tipo Web Panel. São muitos similares. A diferença é que um Web Component pode ser incluído dentro de outro objeto. No entraremos em detalhes neste momento.

Page 315: 93909254 GENEXUS Heuristica Apostila Teorica

PatternsExemplo

Aplicação do pattern Work With à transação Country.

N

1

Ao aplicar o pattern Work With na Transação Country, será criado:• Tela Work With:

• Terá um grid com os atributos CountryId e CountryName• Poderá ordenar e filtrar por CountryName, por ser CountryName o atributo descriptor.• Poderá chamar a transação nos diferentes modos

• Tela View: Mostrará dois tabs. O primeiro tab terá a informação do país selecionado, e o segundo terá a informação dos clientes pertencentes a dito país (porque existe uma relação 1-N entre as transações Country e Customer).

Caso não se queira visualizar o atributo CountryId no grid da tela Work With, basta editar suas propriedades a partir do nó Attributes e colocar a propriedade Visible=False. Não pode ser eliminada porque é a chave primária da transação Country.

Page 316: 93909254 GENEXUS Heuristica Apostila Teorica

PatternsComeçando a associar… janela Work With

Se coloca no país indicado, ou mostra todos os países.

São muitas as propriedades oferecidas nas instancias correspondentes ao padrão Work With, para personalizar o comportamento dos objetos que serão gerados. Na continuação descrevemos algumas delas.

O nó Selection oferece as propriedades relacionadas a tela Work With que se gera para a instância. Seus sub-nós são:

Modes (Ins, Upd, Del, Dis)Este nó permite definir em quais modos se pode chamar a transação. As possibilidades e seus valores por default são:

Insert: TrueUpdate: TrueDelete: TrueDisplay: False

Na instância aparece <default> ao lado de cada uma das propriedades anteriores. Onde se configura este valor por default? Veremos numas páginas mais adiante.

Para cada modo poderá especificar-se uma condição. São fornecidas as seguintes propriedades para esse propósito: Insert Condition, Update Condition, Delete Condition, Display Condition.

Se define uma condição associada a um modo, a chamada para esse modo somente será habilitada a avaliação da condição é verdadeira (Exemplo: CountryId=10).

Page 317: 93909254 GENEXUS Heuristica Apostila Teorica

PatternsModificando a instância do Pattern Work With

� Agregar, eliminar, ocultar Atributos.

� Especificar os modos de chamada à transação

� Definir ordens e filtros.

� Agregar, eliminar, modificar Ações.

� Agregar, eliminar, modificar Tabs.

Posicionar-se no nócorrespondente e pressionar o botão direito do mouse.

Attributes

Este nó permite definir quais atributos desejam mostrar no grid (e para cada atributo, várias propriedades podem ser personalizadas).

Orders

É possível oferecer ao usuário final várias ordens possíveis para ver o resultado da consulta (isto é, as linhas mostrando os dados no grid). Utilizando o botão direito do mouse pode ser definida uma nova ordem (seu nome e composição). Cada ordem pode estar composta por vários atributos (podendo indicar para cada um deles se deseja ordem ascendente ou descendente). Um combobox será apresentado na tela WorkWith oferecendo todas as possíveis ordens a serem selecionadas, para que o usuário final escolha e os dados sejam apresentados no grid ordenados pelo mesmo.

Filter

Este nó permite definir condições de filtro, para que no grid sejam mostrados somente os registros que cumpram com as mesmas.

Actions

O nó Actions permite incorporar ações próprias na tela WorkWith. Isto é, permite agregar botões (dentro ou fora do grid) que chamem aos objetos indicados, com seus parâmetros correspondentes. O nó Actions não está visible por default, estando posicionado no nó Selection e pressionando o botão direito do mouse, a opção Add Actions é oferecida para ser agregada. Uma vez agregado este nó, estando posicionado sobre o mesmo e pressionando o botão direito do mouse, se oferecerá a opção Add Action que permitirá agregar uma ação com seu nome de ação, caption, objeto chamado, etc.

O nó View por sua vez, oferece as propriedades relacionadas a tela View gerada para a instância. Mostra toda a informação de um registro, que foi selecionado no grid do WorkWith (a informação do registro é mostrada em uma aba de um tab control, e além disso tem uma aba com um grid para cada tabela diretamente subordinada, para mostrar a informação relacionada).

Page 318: 93909254 GENEXUS Heuristica Apostila Teorica

318

PatternsPersonalização- Exemplos

1) Ocultar atributo CountryId do grid.

F4

Por que ocultar ao invés de eliminar?

O atributo CountryId, diferente do CountryName, não pode ser eliminado do grid, isso porque é um atributo que se envia a transação ‘Country’ quando o usuário deseja modificar ou eliminar o país mostrado numa linha do grid do Work With.

Page 319: 93909254 GENEXUS Heuristica Apostila Teorica

319

PatternsPersonalização- Exemplos

2) Eliminar modo Delete a partir do grid.

F4

Ao editar as propriedades estando posicionados no nó da instância que se mostra, podemos observar que cada um dos modos que se pode chamar uma transação (para inserir, modificar, eliminar ou incluso mostrar) estão listados como propriedades. Podemos ver também que aparece uma propriedade Export que permite exportar os dados a uma planilha excel.

Outra vez aqui podemos apreciar que cada uma das propriedades possui o valor <default> que ainda não sabemos de onde é pego. Mas se queremos fixar um valor independente de qual seja o default, podemos editar o combo box que apresentará três valores: <default>, ‘true’, ou ‘false’.

Fixamos o valor da propriedade Delete em ‘false’. Podemos ver em execução a repercussão. Não aprece no grid a primeira coluna que contêm a imagem que permitia eliminar o país. Agora não se pode eliminar países a partir dessa tela.

Observe também como desapareceu do grid o atributo CountryId. Ocultamos ele na página anterior.

Page 320: 93909254 GENEXUS Heuristica Apostila Teorica

Patterns

3) Agregar uma ação de chamada a um objeto na tela View Country.

a) Click com o botão direito

sobre o nó selection,

escolha add/actions

b) Click com o botão direito

sobre a ação criada e

escolha add/action.

Personalização- Exemplos

Page 321: 93909254 GENEXUS Heuristica Apostila Teorica

321

PatternsPersonalização - Exemplos

c) Definir a Ação editando suas

propriedades (F4).

Botão fora do grid.

Nome da ação e objeto que se chama.

d) Finalmente em execução, se

observa o botão foi do grid.

Já havíamos definido o objeto BillingProcess para realizar o faturamento do mês de todos os clientes. Aqui estamos agregando um botão fora do grid, que ao pressioná-lo chama outro objeto GeneXus que havíamos criado anteriormente.

Page 322: 93909254 GENEXUS Heuristica Apostila Teorica

322

PatternsAssociando... tela View

O nó View por sua parte, oferece as propriedades relacionadas a tela view que se gera para a instância. Mostra toda a informação de um registro, que foi selecionado no grid do Work With (a informação do registro émostrada em uma aba de um tab control, e além disso tem uma aba com um grid para cada tabela diretamente subordinada, para mostrar a informação relacionada).

Page 323: 93909254 GENEXUS Heuristica Apostila Teorica

323

PatternsPersonalização - Exemplos

1) Tirar atributos CustomerGender e CustomerStatus do tab Customer da tela View Country.

a) Posicionar-se sobre o atributo e eliminá-lo com a tecla de eliminação do teclado ou botão direito/Delete.

Neste caso se não queremos que os atributos CustomerGender e CustomerStatus sejam vistas no grid em execução, não necessitamos ocultá-los. Podemos diretamente eliminá-los.

Page 324: 93909254 GENEXUS Heuristica Apostila Teorica

324

PatternsPersonalização - Exemplos

2) Agregar um filtro por CustomerName no tab Customer.

a) Click com o botão direito

sobre o tab Customer

b) Indicar o atributo sobre o cual filtrar,

editando as propiedades (F4).

Uma vez executado o passo a) e escolher ‘Filter’ aparecerá um novo nó Filter imediatamente depois do nóAttributes, com 2 subnós: Attributes e Conditions.

Depois, no passo b), deverá posicionar-se no subnó Attributes e fazer botão direito, onde se oferece a possibilidade de agregar um atributo de filtro. Ao editar as propriedades, você deverá pressionar o combro box vai mostrar uma janela onde se ingressa o atributo (em nosso caso, CustomerName). Com isto se cria automaticamente uma variável com o mesmo nome que o atributo &CustomerName, que será o control que aparecerá em execução para que o usuário digite ali o filtro. Vejamos o passo seguinte...

Page 325: 93909254 GENEXUS Heuristica Apostila Teorica

325

PatternsPersonalização - Exemplos

(Continuação)

c) Definir a condição correspondente.

Page 326: 93909254 GENEXUS Heuristica Apostila Teorica

PatternsValores por default para as propriedades

Propriedades (F4)

O padrão WorkWith além de gerar objetos novos, também modifica as transações, para que sejam chamadas pelos objetos gerados pelo pattern, agregando a regra parm, etc..Relacionado a isto, cada instância contêm a propriedade UpdateTransaction, que oferece os seguintes valores:

Do not update: A transação não será modificada (web form, regras e eventos serão mantidos).Only rules and events: Somente as regras e eventos serão modificados, o web form não é modificado.Apply WW Style: A primeira vez que o padrão é aplicado, o comportamento será o mesmo que se houvesse selecionado o valor Create Default. A partir da segunda vez que o padrão é aplicado, não se modificará a data área do form da transação (caso tenha sido personalizada com GeneXus e deseja manter), e se modificará o style área, assim como os eventos e regras. Create default: Regras, eventos e form da transação (tanto data área como style área) serão modificados. No que diz respeito ao form, será como selecionar a opção Create default a partir do GeneXus.

O valor por default para esta propriedade é Apply WW Style.

Enquanto as propriedades AfterInsert, AfterUpdate e AfterDelete, permitem definir o comportamento depois que se insere, modifica ou elimina um registro.

Os valores possíveis para cada uma delas são:• Default• Return to caller• Go to View• Go to Selection

Page 327: 93909254 GENEXUS Heuristica Apostila Teorica

PatternsPattern Settings

� Configuração das propriedades gerais (para todas as instâncias)

� Preferences \ Patterns

Aqui estão centralizados os <default> para toda instancia. Podemos ver que o nó Template oferece algumas propriedades que mencionamos na página anterior.

O tamanho da página dos grids do work with, que nas imagens anterior era de 3 (se mostravam em 3 linhas por página do grid) se configura no nó Grid. O valor por default desta propriedade é Page.Rows. Isto é, o valor do domínio enumerado Pages criado por GeneXus automaticamente ao aplicar o pattern na primeira vez. O valor que tem Page é 10. Nós tínhamos alterado para 3 para que não fosse mostrado as imagens complestas.

Page 328: 93909254 GENEXUS Heuristica Apostila Teorica

� Todos os objetos gerados pelos Patterns estão baseados no esquema de Defaults de GeneXus. Cada parte de um objeto é gerada como Default.

� A implementação baseada em Defaults permite ter dinamismo entre a Transação e o padrão

Não é necessário reaplicar o padrão, as alterações são vistas ao abrir o objeto novamente

� O dinamismo é mantido para todas as partes default do objeto

• Opção Edit / Apply Default do Menu para voltar o default de uma parte ou de todas as partes (All parts)

PatternsDinamismo entre a Transação e Patterns

O dinamismo mencionado se mantêm para todas as partes default dos objetos.

Todos os objetos gerados por Patterns estão baseados no esquema de Defaults de GeneXus. Cada parte (Form, Regras, Eventos) de cada objeto é gerado como Default. Caso alguma parte do objeto tenha sido modificada, esta deixa de ser Default.

Por exemplo, se modificar o web form de um WW (não fica como default), e se agrega um novo atributo na TRN, não vai ser atualizado automaticamente o grid WW com esse atributo (ou seja, não será agregado dito atributo).

A implementação baseada em Defaults permite ter dinamismo entre a Transação e o padrão

• Alterar propriedades na definição do padrão (Pattern setting)• Alterações na instância (agregar um novo filtro)• Alterações na Transação (agregar um novo atributo)

Se quiser voltar o dinamismo, deverá ter novamente as partes como default.Para isto, se deve selecionar a partir do Menu Edit / Apply Default (a parte onde se tem aberto o objeto) ou Apply Default (All parts), voltando o default de todas as partes que haviam sido modificadas.

Page 329: 93909254 GENEXUS Heuristica Apostila Teorica

PatternsComo eliminar os objetos gerados por Patterns

� Selecionar a instância, pressionar botão direito / opção “Delete” ou pressionar a tecla DEL. Aparecerá a mensagem:

� Ao confirmar a mensagem

• Se eliminarão todos os objetos gerados por Patterns associados na Transação.• Se eliminarão todos as regras e eventos agregados por Patterns na Transação.• Será desmarcada a opção “Apply this pattern on save” da Transação.

Page 330: 93909254 GENEXUS Heuristica Apostila Teorica

Objeto Web Panel

330

Page 331: 93909254 GENEXUS Heuristica Apostila Teorica

Definição Objetos GeneXus que permitem ao usuário realizar consultas interativas na base de dados através de uma tela em tempo de execução.

Web PanelsGeneralidades

� São flexíveis, para múltiplos usos.

Elementos que as compõem:

Os elementos das web panels são:

Web Form: Cada web panel contem um form Web, o qual deve ser desenhado pelo analista agregando variáveis, atributos, assim como outros controles, para que o usuário possa interagir com o mesmo.

Regras: As regras de uma web panel permitem definir certos comportamentos pontuais de dito objeto. Por exemplo, declarar quais parâmetros recebe, definir quais variáveis não queremos que sejam aceitas no form mas utilizadas para mostrar informação, etc.

Condições: É para definir as condições que devem cumprir os dados a ser recuperados (filtros).

Subrotinas: São rotinas locais na web panel.

Eventos: As web panels empregam a programação orientada a eventos. Este tipo de programação permite definir código ocioso, que se ativa em resposta a certas ações provocadas pelo usuário ou pelo sistema. Nesta seção de uma web panel é onde se define o código ocioso associado aos eventos que podem ocorrer durante a execução da web panel.

Propriedades: São características a serem configuradas para definir certos detalhes referentes ao comportamento geral da web panel.

Ajuda: Permite a inclusão de texto de ajuda, que os usuários podem consultar em tempo de execução da web panel.

Documentação: Permite a inclusão de texto técnico como documentação para os desenvolvedores.

Page 332: 93909254 GENEXUS Heuristica Apostila Teorica

Web PanelsPara o ingresso de dados

Event Enter

1

No exemplo, a web panel contem duas variáveis &StartDate e &EndDate como se mostra acima. Em tempo de execução, o usuário pode ingressar valores nas variáveis &StartDate e &EndDate visto que nas web panels as variáveis por default são de entrada.

No evento Enter da web panel (associado ao botão Billing Generation), se obtêm e gravam as faturas cujas datas se encontrem na faixa especificada.

De modo que a definição desta web panel é para que o usuário ingresse a faixa de datas, e ao selecionar o botão Billing Generation, se execute o processamento das faturas.

Page 333: 93909254 GENEXUS Heuristica Apostila Teorica

Web PanelsPara exibir dados de um registro

parm(in: CustomerId );

Tabela base: CUSTOMER

Customer

{

CustomerId*

CustomerName

CountryId

CountryName

CustomerAddress

CustomerGender

CustomerStatus

CustomerPhoto

}

São mostrados os dados do cliente

blob

2

A web panel mostrada acima foi criada para exibir os dados de um cliente. Precisa ser chamada a partir de outro objeto, passando por parâmetro o código do cliente do qual se quer mostrar a informação.

Uma web panel é um objeto tipicamente utilizado para mostrar informação. Então, quando GeneXus encontra atributos no form, qual intenção do programador ao ter colocado isso? Pois, o que está pedindo implicitamente é que se busque os dados correspondentes a base de dados para mostrá-los.

Com a web panel anterior, GeneXus vai a tabela CUSTOMER e filtra pelo atributo recebido por parâmetro, CustomerId, mostrará a informação do registro encontrado. Que informação? A que reside nos atributos que figuram no form. Mas o atributo CountryName não se encontra na tabela CUSTOMER. Pois acontece o mesmo que com um for each, um grupo de grupo de Data Providers, etc., isto é, desde o registro da tabela base, se acessa o registro relacionado da tabela estendida necessária, para obter o valor do atributo requerido (em nosso caso acessa a tabela COUNTRY para recuperar o valor de CountryName).

As inferências que GeneXus realiza são as seguintes:

Ao se tratar de uma web panel, os atributos que figurem serão de consulta1. Então GeneXus deve acessar a base de dados para recuperar seus valores. De quais tabelas? Vai depender se a Web panel possui grids ou não:

• Web panel plana (sem grid): os atributos estão “soltos” no form, como no caso que estamos mostrando. Se isso acontece, é porque o analista necessita acessar a informação de um registro de uma tabela (e eventualmente dos registros relacionados pela tabela estendida), como é o caso do exemplo. Neste caso, a web panel estará bem programada se além disso se agregar um filtro que determine “esse” registro a ser mostrado. Em nosso caso, temos a regra parm que ao receber no atributo PK da tabela somente vai recuperar um registro. GeneXus determina uma tabela base da web panel, assim como faz para um for each. Como? Buscando a mínima tabela estendida que contenha os atributos..

• Web panel com uno ou mais grids: veremos em seguida, mas já podermos pensar... Qual o sentido de colocar um grid? Mostrar informação repetitiva. No caso geral: cada grid mostra muitos registros de uma tabela (e sua informação associada).

1 Ao contrário do que acontece com os atributos nas transações (exceto os inferidos ou os que tem regra noaccept ou propriedade Enabled desabilitada).

Page 334: 93909254 GENEXUS Heuristica Apostila Teorica

Web PanelsPara exibir múltiplos registros: Grids

Exemplo: Mostrar todas as Faturas

CUSTOMER COUNTRY Tabela base: CUSTOMER

3

O que diferencia está web panel da anterior é que ela não é plana.

Quando se incluiu um grid num form, se está indicando que vai mostrar uma quantidade indefinida de dados (neste caso, clientes).

Visto que nesta web panel tem envolvidos atributos, GeneXus infere que deseja acessar a base de dados. Simplesmente dizendo quais atributos deseja mostrar, sem necessidade de mais informação. Existe um grid, tem atributos, então, necessariamente terá tabela base, isto é, a tabela da base de dados navegada em busca da informação requerida.

Se ao invés de mostra esta informação em tela, quisermos uma listagem, vamos criar um procedimento com um print block ‘customer’ com os atributos CustomerName e CountryName e no source programaríamos:

for eachprint customer

endfor

Isto é a análogo, somente que o for each está implícito, não tem que especificá-lo. Cada linha do grid que se carrega, é como o print que se executa em cada iteração do for each da listagem.

Das tabelas CUSTOMER e COUNTRY e da relação entre ambas é Na1, GeneXus determina a tabela basedesta web panel (sendo que a tabela estendida seja a mínima que cumpre que contenha todos os atributos referidos). Observe que este exemplo somente difere do anterior, que os atributos aparecem num grid, e portanto, não precisa filtrar, ficando somente registro de CUSTOMER. Nesta web panel não tem regra parm que estabeleça filtro algum.

Também conseguiremos mais adiante que esta web panel além de mostrar os clientes da base de dados no grid, também permite filtrar os clientes que se quer ver em cada oportunidade, seja por nome do cliente, ou por ambos. Por isso as variáveis aparecem no form.

INVOICE CUSTOMER

Page 335: 93909254 GENEXUS Heuristica Apostila Teorica

335

Web Panels... Load automático

CustomerId CustomerName CountryId .

1 Susan Jones 2 .

2 Richard Smith 2 .

3 Martina Rodríguez 1 .

4 Hugo Romero 4 .

... ... ... .

Customer tabela

CountryId CountryName

1 Uruguay

2 United States

3 Italy

4 Venezuela

... ...

Country table

load

loadload

load

For each implícito:para c/customer buscar nome de país associado e Load � se carregalinha no grid.

Base de dados

3

Quando GeneXus pode determinar automaticamente uma tabela a percorrer para carregar as linhas do grid, o faz, e nesse caso não terá necessidade dessa informação. É por isso que falamos que nesse caso tem um for each ‘implícito’. Depois veremos casos em que isso não acontece (grids sem tabela base).

Observe o exemplo, que se na tabela existem 4 registros, se carregam uma a um os quatro.

Se agora queremos que o usuário possa filtrar os clientes que deseja ver...entra em questão as variáveis que definimos na parte fixa do form, como veremos na página seguinte.

Page 336: 93909254 GENEXUS Heuristica Apostila Teorica

336

Web Panels

Exemplo: Mostrar os clientes que cumprem condições:

Por default de entrada

...filtrando

3

Observe como na janela de propriedade do control Grid, aparece un de nome ‘Conditions’. Clicando no combo abre um editor para especificar as condições booleanas que devem cumprir os registros para ser carregadoscomo linhas do grid.

É por essa razão que foi agregado as variáveis &CustomerName e &CountryName no form da web panel, para que o usuário possa ingressar ali valores que operem como filtros sobre os dados a mostrar. Em nosso caso, estabelecemos filtros com o operador like. As variáveis na parte plana do form de web panels são por default de entrada. Depois veremos que se estiverem em grids são por default de saída.

Observe que as condições (separadas com “;”) equivalem as que apareciam nas cláusulas where de um for each (ou grupo repetitivo de data provider).

Da mesma maneira, por questões de otimização, pode determinar, igual se fazia com um for each, critério de ordenação da tabela percorrida, como se mostra acima no exemplo.

Nota: Assim mesmo, da mesma forma que num procedimento, não somente podem estabelecer condições locais ao grid (for each), mas também gerais, mediante o selector Conditions. Isto tem sentido quando tiver mais de um grid (for each), para não ter que repetir cada vez a mesma condição.

Page 337: 93909254 GENEXUS Heuristica Apostila Teorica

337

Web Panels...com refresh automático

DBDB

Refresh

Server

Client

LoadLoad...

Eventos do sistema: Refresh e Load...

3

A propriedade Automatic Refresh que se encontra a nível da Web Panel pode ter os seguintes valores:• When variables in conditions change (valor por default): depois de chamar automaticamente o refresh, se dispara o evento Load carregando o grid segundo os novos valores das variáveis.• No

Dependendo do tipo de dados do filtro, e do control web utilizado para filtrar, a condição será aplicada quando se estádigitando ou ao abandonar o campo.No caso de filtros em controles edit, para tipo de dados Character, são aplicados quando o usuário vai digitando. Para tipo de dados Date, DateTime e Numeric, as condições são avaliadas ao sair do campo.No caso de filtros combo boxes ou dynamic combos, as condições são avaliadas quando se abandona o campo. Para Check boxes e Radio buttons, as condições são avaliadas quando o valor é alterado.

Execução: o que acontece no cliente e no servidor ao ter a propriedade por default e um grid com tabela base?

1ª execução (variáveis vazias):For each CUSTOMER

guardar em memória CustomerNameacessar o registro de COUNTRY relacionado

guardar em memória CountryNamecarregar (load) linha no grid com ambos valores

N-ésima execução (altera o valor da variável das conditions):Automaticamente no browser do cliente se detecta a mudança � refresh no servidor para voltar a carregar o grid com os registros que cumpram as condições (com os novos valores das variáveis) � load para cada linha.

Conclusão: Existem dois eventos do sistema que ocorrem no momento da carga do form (Refresh) e da carga de cada linha do grid (Load). Como veremos, estes eventos pode associar código para que se execute nesses momentos específicos...

Page 338: 93909254 GENEXUS Heuristica Apostila Teorica

338

Web Panels... programando o evento Load

Intenção: para aqueles clientes com estado ‘On Hold’, para poder ativá-los marcando check box e pressionando botão ‘Activate’. Antes queremos:

Agregamos ao grid atributo CustomerStatus e a variável &select booleana...

1. Somente habilitar check box para os ‘On Hold’:

Quando se carrega cada linha do grid, se o valor do atributo CustomerStatus da tabela CUSTOMER a ser carregado é On Hold, habilitar check box...

3

Ampliaremos a funcionalidade de nossa web panel, permitindo ver o estado de cada cliente, e para aqueles que estiverem ‘On Hold’, brindando a possibilidade de os passar para o estado ‘Active’.

Para fazer isto, agregaremos ao grid o atributo CustomerStatus que mostra o estado, e uma variável booleana &Select, que permitirá ao usuário selecionar aqueles clientes que deseja ‘ativar’. Além disso um botão para efetivamente ativar todos os clientes marcados. Mas isto o faremos num segundo momento.

Observe que se o tipo de dados da variável &select booleano, por default aparece no grid como um check box. Para assegurar que o usuário somente tente ‘ativar’ clientes ‘On Hold’, desejamos que somente apareça habilitado este check box quando corresponde... para ele necessitaremos programar a carga de cada linha, isto é, o evento Load...

Page 339: 93909254 GENEXUS Heuristica Apostila Teorica

339

Web Panels... programando o evento Load

Se dispara uma vez para cada registro da tabela base a ser carregado... (tendo código programado ou não)

CustomerId CustomerName CustomerStatus ...

1 Susan Jones A ...

2 Richard Smith O ...

3 Martina Rodríguez C ...

4 Hugo Romero A ...

... ... ...

Customer tabela

3

Na seção Events da web panel, programamos o evento Load do grid que vemos acima. No exemplo, customerGrid é o nome que demos ao control grid no form.

Ao se tratar de uma web panel com um único grid, também poderíamos ter programado o evento Load:

Event Loadif CustomerStatus = Status.OnHold

&select.Enabled = 1else

&select.Enabled = 0endif

endevent

Isto é, no caso de uma web panel com um único grid, não é necessário qualificar o evento com o nome do grid. Igualmente recomendamos fazer, antecipando a possibilidade futura de agregar outro grid no form da web panel.

O evento Load é disparado para cada linha que vai carregar no grid, encontrando este comando ou não. O que fazemos no exemplo é aproveitar este momento imediatamente anterior a carga, para efetuar uma ação. E esse é o código que incluímos no evento.

Agora sim, estamos em condições de implementar a ‘activate’, para isso precisamos associar ao botão um evento, que poderá ser o evento Enter ou um de usuário...

Page 340: 93909254 GENEXUS Heuristica Apostila Teorica

340

Web Panels... evento Enter

2. Ativar os clientes ‘On Hold’ selecionados:

For each line in customerGridif &select

&customer.Load( CustomerId )&customer.CustomerStatus = Status.Active&customer.Save()Commit

endifendfor

Comando For each line...Percorre linhas de um grid

&customer � BC ‘Customer’

3

No exemplo, quando o usuário pressiona o botão ‘Confirm’, necessitamos percorrer todas as linhas do grid, e para cada uma delas, se o usuário marcou a variável boleana &Select f (check box), devemos alterar o estado do cliente correspondetne, de ‘On Hold’ a ‘Active’.

Ao inserir o botão no form da web panel, e editar suas propriedades, por default se pode observar que o botao esta associado ao evento Enter (ver propiedad OnClickEvent).

El Enter será un evento del sistema, que se ejecuta tanto cuando el usuario hace clic sobre el control asociado, como cuando presiona la tecla Enter.

En este ejemplo veremos a la vez:• Posibilidad de definir eventos de usuario y asociárselos a controles o de utilizar el evento Enter del sistema.• Comando For each line, para recorrer las líneas ya cargadas en un grid.• Variables en un grid pasan de ser Read only (de salida) por defecto, a ser de entrada, cuando se utiliza comando for each line en ese grid (también cuando se programan eventos OnClickEvent, Click, etc., sobre alguna columna del grid).

Obsérvese que el comando For each line sólo tiene en común con el comando For each estudiado antes, el hecho de representar una estructura repetitiva. La diferencia más importante: mientras el for each recorre registros de una tabla (base) de la base de datos, el for each line recorre las líneas de un grid.En nuestro ejemplo hemos definido una variable &customer, Business Component Customer, mediante la cuál cambiaremos a estado ‘Active’ todas las líneas del grid marcadas por el usuario. Para ello recorremos el grid con el comando for each line.

Page 341: 93909254 GENEXUS Heuristica Apostila Teorica

341

Web Panels... o evento de usuário

2. Ativar os clientes ‘On Hold’ selecionados:

For each line in customerGridif &select

&customer.Load( CustomerId )&customer.CustomerStatus = Status.Active&customer.Save()Commit

endifendfor

3

Outra possibilidade, ao invés de utilizar o evento do sistema Enter, é definir um evento de usuário. Isso érealizado seguindo os passos que estão acima.

Como podemos ver, a maioria dos controles presentes em um form tem a propriedade OnClickEventassociada. Essa propriedade permite especificar um evento a ser disparado quando o usuário faz clique sobre o controle. Poderá ser um evento do sistema (Refresh, Enter) ou um evento definido pelo usuário.

Page 342: 93909254 GENEXUS Heuristica Apostila Teorica

342

Web Panels... Variáveis de grid

• Por default todas as variáveis de um grid são Read-Only

• For each line [in grid] ou qualquer evento sobre as linhas ou colunas (OnClickEvent, Click, DblClick, IsValid, etc): modifica o valor por default e todas as variáveis do grid passam a ser de entrada. Para ter algumas de saída:

Propriedade: Read Only

3

A parte fixa da web panel por default é de entrada, como já vimos anteriormente para as variáveis utilizadas para filtrar os clientes (customers) mostrados no grid.

Como mostrar dados no gridPor default todo atributo e variável que está dentro de um grid se mostra em execução como texto, porque é

unicamente de leitura e por consequencia não pode ser alterado.

Como aceitar dados em um gridÉ possível aceitar dados nas variáveis de um grid dependendo da programação dos eventos existentes no

objeto:

1. Se dentro de um evento da web panel ter o comando For each line, todas as variáveis que estão dentro do grid passam a ser de entrada. É possível indicar neste caso quais são as variáveis que não podem ser modificadas através da propriedade ReadOnly.

2. Se dentro da fila tem algum controle com um evento click, dblClick, etc.. associado (ou evento de usuário especificado na propriedade OnClickEvent), acontecerá o mesmo.

Page 343: 93909254 GENEXUS Heuristica Apostila Teorica

343

Web Panels...ocultar atributos do grid e permitir seleção de uma linha

Event ‘Select customer’CustomerView.Call( CustomerId )

endevent

3

Continuamos ampliando nosso exemplo; agora queremos que o usuário possa selecionar uma linha do grid (um cliente) e pressionando botão ‘Select customer’ para chamar a web panel que havíamos implementado anteriormente.

Neste exemplo vemos duas funcionalidades:• A necessidade de colocar uma coluna no grid oculta (não visível).• Permitir que o usuário selecione uma linha do grid para fazer algo com ela.

Por que colocar a coluna correspondente a CustomerId e ocultá-la, ao invés de não agregar o atributo? Faça a seguinte reflexão: o atributo CustomerId enviado por parâmetro ao executar o evento ‘Select customer’, de onde é extraído? Da base de dados? Não, é o que está carregado no grid. Mais especificamente, para cada grid existirá um arquivo temporário que contem a quantidade de colunas que o grid possuir, visíveis e ocultas. Quando o usuário seleciona no grid a segunda linha, e pressiona o botão ‘Select customer’, está posicionado nesse arquivo temporário, correspondente a essa linha (e nunca na base de dados!). É por esta razão que se não colocarmos nenhuma coluna correspondente a CustomerId no grid, não estaríamos passando valor algum a CustomerView.

Para que o usuário possa selecionar uma linha do grid, é suficiente ‘prender’ a propriedade ‘AllowSelection’ do grid.

Page 344: 93909254 GENEXUS Heuristica Apostila Teorica

344

Web PanelsDeterminação tabela base

3

Event ‘Activate’For each line in customerGrid

if &select &customer.Load( CustomerId )&customer.CustomerStatus = Status.Active&customer.Save()Commit

endifendfor

endevent

Event ‘Select customer’CustomerView.Call( CustomerId )

endevent

Event customerGrid.Loadif CustomerStatus = Status.OnHold

&select.Enabled = 1else &select.Enabled = 0endif

endevent

3. Eventos: atributos soltos(fora de for eachs)

2. Grid: • atributos das colunas (visíveis+invisíveis)• propriedade Order• propriedade Conditions• propriedade Data Selector

+

1. Atributos soltos no form (fora do grid)

+

Como GeneXus determina uma tabela base para percorrer automaticamente para carregar o grid da web panel?

Se existir algum atributo em pelo menos um dos 3 lugares mencionados, GeneXus poderá encontrar a tabela base. Para determinar a tabela base, ele extrai os atributos encontrados ali (parte fixa do Form, no Grid, tanto nas colunas como nas propriedades Order, Conditions ou using Data Selector, e nos eventos programa programados no selector de Eventos, somente os atributos que estejam ‘soltos’ dentro do evento, isto é, fora de um comando for each de acesso a base de dados), e determina a mínima tabela estendida que os contenha. A tabela base dessa estendida, será a percorrida automaticamente e carregada com o Load.

Observe que somente programamos o evento Load para tomar a decisão para cada línea que vai ser carregada no grid, que habilitará ou não para a mesma variável &select que permitirá ao usuário marcar o check box.

Importante: A forma de determinação da tabela base de um grid dependerá se existir outro grid na web panel ou se é o único. O resumo apresentado aqui corresponde a um único grid. Neste caso se diz que a própria Web panel tem tabela base. É a do grid. Quando existir mais de um grid na web panel, isto não vai ter sentido, e cada grid passará a ter cada grid passará a ter ou não tabela base. Veremos a forma de determinação das tabelas bases nesse caso, quando tratemos o caso de múltiplos grids em uma web panel.

Page 345: 93909254 GENEXUS Heuristica Apostila Teorica

345

Web Panels 4

Para exibir múltiplos registros: Grid (sem tabela base)...

Mostrar o total de faturas por dia (podendo ter um filtro entre as datas informadas)

Cada línha do grid não corresponde a cada registro da tabela INVOICE, o que faz é agrupar todas as faturas de uma data e totalizar … se fosse um pdf, seria implementado.

For each order InvoiceDatewhere ...

&InvoiceDate = InvoiceDate&Amount = 0for each defined by InvoiceDate

&Amount += InvoiceAmountendforprint InvoiceInfo

endfor

Estamos apresentando aqui outro exemplo, para que possamos observar um caso que surge a necessidade natural de implementar um grid sem tabela base.

O caso de implementação natural de um grid com tabela base, é quando deseja que seja carregado para cada registro de uma tabela, uma linha do grid (1 registro – 1 linha). No caso que se quer carregar uma linha do grid como produto a ser lido de vários registros da base de dados (N registros – 1 linha), como produtos de cálculos, etc., é mais natural implementar o grid sem tabela base.

O caso do exemplo: não queremos carregar para cada fatura uma linha, mas sim queremos agrupar as faturas por data, e para cada grupo, carregar uma linha que some seus valores. Estamos falando de um controle de corte. Se tivéssemos que implementar uma listagem PDF ao invés de uma web panel, saberíamos como programar (como o fazemos acima) . Vejamos como implementar com uma web panel...

Page 346: 93909254 GENEXUS Heuristica Apostila Teorica

346

Web Panels 4

Para exibir múltiplos registros: Grid (sem tabela base)...

Não tem atributos (em nenhum dos 3 pontos anteriores) � não tem tabela base

GeneXus não pode inferir carga automática: � tem que programar� evento Load ocorre somente 1vez

Ordem de carga de uma linha no grid (as variáveis assumem valores nesse momento)

O objetivo do comando LOAD é agregar um linha num grid. É necessário quando o grid não tem tabela base, visto que nesse caso não será agregado nenhuma linha de forma automática. O evento Load vai ocorrer uma vez, e o grid retornará vazio caso não seja programado. Portanto neste caso é imprescindível que seja programado, de acordo com a lógica correspondente. Uma vez que for atribuído a cada variável seu valor, e se deseja agredar uma linha ao grid, o comando LOAD deverá ser programado.

O comando LOAD somente pode ser especificado dentro do evento Load do grid de uma web panel.

Observe que neste caso a implementação fica por conta do analista. Frente ao caso do grid com tabela base, neste GeneXus realiza menos inferências.

Page 347: 93909254 GENEXUS Heuristica Apostila Teorica

347

Web Panels 4

Para exibir múltiplos registros: Grid (sem tabela base)...

Refresh não é automático! � Agregamos botão associado ao evento Enter ou de usuário, sem código, ou diretamente ao Refresh.

No caso de um grid sem tabela base, os filtros dos dados são programados dentro do código implementado para carga (o do Load). Aqui não tem o refresh automático. Isto é, quando o usuário modifica os valores das variáveis que interveem nos filtros, GeneXus não sabe que tem que voltar a carregar o grid.Para isso deverá, por exemplo, agregar um botão associado ao evento Enter, ou a um evento de usuário, sem código, devido ao fato que somente precisamos dele para que um Refresh seja realizado, ou seja, para que o servidor volte a carregar a web panel.

Sobre os eventos disponíveis e a ordem em que são disparados, entraremos em seguida.

Page 348: 93909254 GENEXUS Heuristica Apostila Teorica

348

Web PanelsProgramação dirigida por Eventos

• Evento Start• Evento Refresh• Evento Load• Evento Enter• Eventos de Usuário• Evento TrackContext (no curso não será visto)

• Associados a controles do form (dependendo do tipo de controle):• Evento Click, DblClick, RightClick, IsValid, Drag, Drop, etc.

Nota:Refresh, Enter, de Usuário:Através da propriedade OnClickEvent podem Estar associados a controles do form

Em toda Web panel existem eventos do sistema que podem ser programados. Alguns ocorrem sempre, em cada execução da web panel (como o Start, Refresh, Load), outros se forem declarados e o usuários realiza as ações necessárias para provocá-los (Enter, definidos pelo usuário, TrackContext).

Assim mesmo, quase todos os controles que aparecem no form brindam a possibilidade de disparar um evento quanto o usuário faz clic com o mouse (os hiper-links aparecem em execução); de duas maneiras diferentes:

1. Editando as propriedades do controle (F4), e definindo um evento de usuário na propriedade OnClickEvent, ou associando o evento Enter ou o Refresh.

2. Dando um nome ao controle e na seção de Eventos programando:

Event nomeControl.click…

Endevent

Com esta última alternativa não teremos que definir um evento de usuário, mas sim teremos que programar o evento click do controle. O mesmo ocorre com os eventos DblClick, RightClick, IsValid... (quando fizer duplo clique, botão direito, etc.).

Sobre os eventos associados as ações sobre os controles (click, dblclick, drag, drop, etc.) não veremos no curso presente. Em nosso wiki tem informação detalhada, assim como no Help de GeneXus.

Sobre o evento TrackContext somente mencionaremos que é possível detectar mudanças no valor de um dado controle (grid, variável, etc.) e nesse caso disparar este evento baseado ao valor modificado, tomar una ação.

Page 349: 93909254 GENEXUS Heuristica Apostila Teorica

• É um evento do sistema, que ocorre automaticamente sempre que se faz Get ou Post e é o primeiro evento que se executa.

• Os valores de atributos não são conhecidos, exceto os recebido por parâmetro. Isto se deve que ainda não foi efetuado a consulta.

• Exemplo: se pode utilizar para que um controle do form não apareça visível, para carregar um bitmap, para associar um Link a outro controle, etc.:

Event Start&var.Visible = 0&Update = LoadBitmap("images/edit.gif")newControl.Link = Tcustomer.link()

endevent

Web PanelsEvento Start

Page 350: 93909254 GENEXUS Heuristica Apostila Teorica

350

Web PanelsEvento Refresh – Evento Load

• Eventos do sistema, codificáveis, associados a carga da Web Panel. Primeiro é executado o Refresh e depois sempre o Load.

• Se o grid tem tabela base

• Se o grid não tem tabla base

Load é executado N vezes: Um para cada linha

Load é executado somente 1 vez: Dentro do evento a carga da linha do grid terá que ser programada, Para carregar, comando Load.

Quando a web panel é com tabela base, ao produzir-se o evento Refresh se acessa a base de dados, a essa tabela base (associada a web panel), e se percorre carregando os registros que cumpram as condições (conditions do grid e gerais). Vai ocorrer nesse processo um evento Load para cada registro em que estiver posicionado, imediatamente antes de carregá-lo. Isto nos permite realizar alguma operação que requeira desse registro ( e de sua estendida), antes de efetivamente carregá-lo no grid. Imediatamente depois de executado o código associado ao evento Load, será carregado a linha do grid e o ponteiro é passado ao seguinte registro da tabela base, para realizar o mesmo (evento Load, carga da linha). Este processo se repetirá até carregar todas as linhas do grid.

Se uma web panel é sem tabela base, GeneXus não pode determinar automaticamente uma tabela da base de dados a percorrer para mostrar a informação que se apresenta no form. Neste caso no form somente aparecem variáveis (e não atributos) e também vão ocorrer os eventos Refresh e Load, somente que o evento Load é executado uma única vez, visto que não estará posicionado em nenhum registro de nenhuma tabela.Dentro desse evento a carga terá que ser codificada, que pode ser que precise acessar a base de dados (ex: comando for each) o não (vamos supor que seq queira carregar o grid com informação obtida ao percorrer um SDT collection, efetuar alguma transformação sobre seus itens ... ou carregar linhas no grid produto de cálculos). O controle da carga do grid, fica aquí nas mãos do analista, utilizando o comando Load. Este comando somente é válido dentro do evento com o mesmo nome. Note como no caso do grid com tabela base, este comando não é necessário.

Page 351: 93909254 GENEXUS Heuristica Apostila Teorica

351

Web PanelsRefresh automático

• Válido somente para Grid com tabela base

• Para Grid sem tabela basenecessariamente tem que associar evento

A propriedade Automatic Refresh que se encontra a nível da Web Panel pode tomar os seguintes valores:

• When variáveis in conditions change (valor por default): automaticamente provocam o refresh, se dispara o evento Load carregando-se o grid segundo os novos valores das variáveis.• No: para que o conteúdo do grid se renove depois de alterar os filtros, o usuário deve realizar uma ação:

Se o grid é com tabela base:• As alterações nas variáveis dos filtros se detectam automaticamente. • Ao pressionar a tecla Enter, se dispara o Refresh da página (não o código do evento Enter, ainda que esteja programado).• Ao fazer click num botão ou numa imagem associados a um evento de usuário, imediatamente depois de alterar o valor de uma variável das conditions do grid, se executa este evento e atualiza imediatamente depois a página. Se o evento for o Enter, este evento NÃO se executa.

Se o grid é sem tabela base:• As alterações nas variáveis dos filtros NÃO se detectam automaticamente • O usuário deve fazer click no botão ou na imagem associados a um evento Refresh ou a umevento de usuário que chame um Refresh.

Page 352: 93909254 GENEXUS Heuristica Apostila Teorica

352

Web PanelsEventos – Ordem de disparo

• Start• Leitura de variáveis na tela

• Evento enter ou de usuário (click, dblclick, etc., que produziu post)

• Refresh• Load

• POST: As outras execuções da web panel.

• GET: Quando a Web Panel é aberta.

• Start• Refresh• Load

Os eventos disparados e sua ordem depende se a web panel está sendo aberta (Get) ou se já estava aberta e está efetuando uma ação posterior a um botão (Post).

Acima mostramos com exemplos o caso geral.

1a. vez: Start + Refresh + Load N-ésima vez: Start + Leitura de variáveis da tela + Evento que produziu o Post + Refresh + Load.

Este é o caso geral... existe uma exceção...

Page 353: 93909254 GENEXUS Heuristica Apostila Teorica

353

Web PanelsEventos – Ordem de disparo

• Exceção:

• Alguns eventos de usuário devem ser executado no Server mas outros não � são executados somente no Cliente (todos os outros eventos não precisam ser executados no server: Start, Refesh e Load).

• Evitando roundtrips desnecessários ao servidor, e reduzindo a quantidade de dados que viajam de um lado a outro.

• Exemplo: um evento que altera o estado de um controle, não precisa ser executado no server.

• GeneXus tem inteligência para determinar. Para o programador é transparente

Event ‘UserEvent’&CustomerId.Visible = 0

endevent

Internamente GeneXus determina as entradas e saídas de cada evento. Se em suas entradas, se requerem de ações executas no Server, então o evento se executará no Server. Por exemplo, se entre as entradas de um evento de usuário X, se encontra alguma das saídas do evento Start (do server), então o evento de usuário se executará no Server.

Se o código do evento não requer que seja executado no servidor, então por performance, será executado no cliente, como código javascript.

De todas as maneiras o analista GeneXus não deve se preocupar com estes assuntos, visto que em todo caso será o GeneXus que terá a inteligência de resolver onde vai executar o evento.

Page 354: 93909254 GENEXUS Heuristica Apostila Teorica

354

Web PanelsMúltiplos grids – Grids paralelos

filtrar faturas por dia do cliente

Aqui apresentaremos um exemplo que reúne os dois casos que viemos estudando: a web panel mostrada em execução tem dois grids paralelos: um que mostra informação dos clientes do sistema, e outro que mostra faturas, totalizadas por dia.No nosso caso, queremos além disso relacionar os dados, de tal maneira que quando o usuário seleciona um cliente, sejam mostradas somente as faturas desse cliente. Incluso ao estabelecer filtros de datas, também queremos que vá para o cliente selecionado (e não para todos os clientes).

Quando uma web panel contem mais de um grid em seu form, GeneXus não determina uma única tabela base associada para web panel, mas sim uma tabela base associada a cada grid.

Atributos que participam na determinação da tabela base de cada grid:

• Os incluídos no grid (são levados em consideração os atributos visíveis como os não visíveis, ocultos/hidden)• Os referenciados na Order e Conditions locais do grid

A diferença do que acontecia para uma web panel com somente um grid, no caso de múltiplos grids os atributos da parte fixa da web panel não participam na determinação da tabela base de nenhum deles, mas deverão pertencer a tabela estendida de algum (para que seja possível inferir seus valores).Caso isso não seja respeitado, ao especificar a web panel, se mostra na listagem de navegação resultante, um warning advertindo desta situação.

Os atributos utilizados nos eventos da web panel tampouco participam na determinação da tabela base de nenhum dos grids. Os atributos que se inclui nos eventos fora de comandos for each, deverão pertencer a tabela estendida de algum dos grids (da mesma forma como da parte fixa).

Page 355: 93909254 GENEXUS Heuristica Apostila Teorica

355

Web PanelsMúltiplos grids – Grids paralelos

Event Start&CustomerId.Visible = 0

endevent

Event ‘Select customer’&CustomerId = CustomerId

endevent

Event inoicesGrid.Loadfor each order InvoiceDatewhere InvoiceDate >= &startDate when...where InvoiceDate <= &endDate when...where CustomerId = &customerId when

not &customerId.IsEmpty()...

endevent

GeneXus não relaciona as cargas

Esta web panel poderia ter sido implementada de diferentes formas e obtendo o mesmo resultado na execução.

Acima podemos ver a implementação mais natural: o primeiro grid tem tabela base e o segundo não tem. Mas poderia ter sido implementada de forma contrária, com variáveis no primeiro grid e tendo que realizar a carga dos clientes a mão no Load, e atributos no segundo grid, e algumas coisas a mais para obter o controle de corte, sendo um grid com tabela base. Ou qualquer combinação (ambos grids com tabela base, ou nenhum com tabela base).

O importante é, uma vez escolhida a implementação mais natural ao caso, realizá-la corretamente.

Em qualquer dos casos, ainda que a informação a ser carregada em mais de um grid se encontre relacionada na base de dados, GeneXus não assume nenhuma relação entre os dados na hora de carregar um grid e o outro. É análogo o caso de um par de for eachs paralelos no Source de um procedimento.

Acima podemos ver a web panel que temos o grid com os grids, agregamos a parte de visualização de faturas por data que implementamos na web panel. Mas não basta simplesmente unir as duas web panels... para poder relacionar as cargas dos grids, a lógica deve ser agregada. Em nosso caso desejamos que uma vez que selecionarmos um cliente do primeiro grid, certa lógica precisa ser agregada. Em nosso caso desejamos que uma vez um cliente for selecionado no primeiro grid, as faturas carregadas no segundo grid não sejam de todos os clientes, mas somente do selecionado.

Para isso devemos ter duas coisas: agregar uma variável &CustomerId para armazenar o id do cliente selecionado ao pressionar ‘Select customer’, e depois agregar um filtro pelo valor dessa variável quando se carrega o grid de Invoices. Assim mesmo precisa obrigatoriamente colocar essa variável no form para que tudo funcione corretamente ... como esperamos... e na análise abaixo encontraremos a razão.

Page 356: 93909254 GENEXUS Heuristica Apostila Teorica

356

Web PanelsMúltiplos grids – Grids paralelos

1ª. execução

Start � oculta &customerId

Refresh

customerGrid.RefreshcustomerGrid.LoadcustomerGrid.Load

....

invoicesGrid.RefreshinvoicesGrid.Load

Vamos analisar o que acontece quando a web panel é executada pela primeira vez.

Primeiro o evento Start é executado, em nosso caso a variável &CustomerId é ocultada.

Podemos ver na imagem, que um evento Refresh genérico é produzido, depois serão produzidos as cargas de todos e cada um dos grids encontrados na web panel, da esquerda para a direita de cima para baixo.

Um evento Refresh próprio ocorre e o evento Load (se possuir tabela base são N vezes e se não tiver tabela base somente 1 vez).

Observe que nosso caso, o grid de cliente tem condições para serem carregadas, pelas variáveis de filtro &customerName e &countryName, não são aplicadas se estiverem vazias (visto que ambas cláusulas condicionais tem when not &var.IsEmpty())

O segundo grid é sem tabela base, mas como já vimos, o evento Load era executado um for each com cláusulas where, serão carregadas somente aquelas linhas que as condições são cumpridas. São três:

where InvoiceDate >= &startDate when not &startDate.IsEmpty()where InvoiceDate <= &endDate when not &endDate.IsEmpty()where CustomerId = &customerId when not &customerId.IsEmpty()

Observe que nesta primeira execução &customerId está vazio, o filtro não é aplicado e todas as faturas do dia é carregada, de todos os clientes.

Page 357: 93909254 GENEXUS Heuristica Apostila Teorica

357

Web PanelsMúltiplos grids – Grids paralelos

2ª. execução Selecionar um cliente:

Start � oculta &customerId

Refresh

customerGrid.RefreshcustomerGrid.LoadcustomerGrid.Load

....

invoicesGrid.RefreshinvoicesGrid.Load

Leitura das variáveis na telaEvento que produziu o post

Event ‘Select customer’&CustomerId = CustomerId

endevent

O usuário seleciona o cliente do grid o cliente correspondente da linha e pressiona o botão ‘Select customer’.

Uma ação é detectada e ocorre um post ao servidor, quem executa o Start (ocultando a variável), depois as variáveis da tela são lidas (&customerId no momento está vazia, são consideradas não somente as variáveis da tela, as que são definidas, mas também a informação completa da linha selecionada pelo usuário com o mouse, entre ela, o valor de CustomerId, coluna do grid), depois o código do evento que produziu o post éexecutado, no nosso caso, ‘Select customer’. Aqui a variável &customerId toma o valor do CustomerId da linha escolhida. Depois ocorre o evento Refresh geral que dispara o Refresh e Load de cada grid.

Portanto, cada grid é executado executando as conditions. O primeiro se carregado como antes, porque nenhuma de suas conditions variou. O segundo, agora se tiver um valor para &customerId, somente serámostrado as faturas do cliente.

Você poderia se perguntar porque precise colocar a variável oculta no form. Simplesmente porque não se pode usar como variável dentro do programa, se não estiver no form e torná-la invisível. Todavia com esta segunda execução não podemos responder a pergunta. De fato, se analisarmos, pode ser visto facilmente que teríamos o mesmo comportamento se somente fosse atribuído valor a variável no ‘Select Customer’ sem colocá-la no form.

Vamos ver o motivo com a execução seguinte....

Page 358: 93909254 GENEXUS Heuristica Apostila Teorica

358

Web PanelsMúltiplos grids – Grids paralelos

3ª. execução Filtrar as faturas para o cliente selecionado

Start

Refresh

customerGrid.RefreshcustomerGrid.LoadcustomerGrid.Load

....

invoicesGrid.RefreshinvoicesGrid.Load

Leitura das variáveis na tela

Evento que produziu o post (vazio)

&customerId �invisible

Agora o usuário já selecionou o segundo cliente, e o que deseja fazer é filtrar suas faturas por data (não quer visualizar todas).

Para isso especifica os filtros de data, e pressiona o botão ‘Search’, que produzirá um post no servidor.Então o código do Start é executado, depois são lidas as variáveis da tela: aqui está o motivo de ter colocado &customerId no form. O valor de &customerId é lido, permanecendo até que o usuário não selecione outro cliente do grid e pressionar o botão ‘Select customer’... esta variável presente no form, é a forma de manter a memória em execuções.Lembre que cada vez que se faz um post ao servidor, é uma nova execução da web panel, já que as variáveis começam novamente vazias. Por isso que o segundo passo: “Leitura de variáveis da tela” é fundamental.Agora sim, seguindo o exemplo, as variáveis da tela são lidas &customerId invisível (visible=0), junto com as variáveis &startDate e &endDate. E depois, como sempre, a carga é executada (Refresh genérico + Refresh e Load de cada grid).Alterando as condições do for each que carrega o segundo grid, agora aparece somente as faturas do segundo cliente, entre as datas estipuladas pelo usuário.

Se agora o usuário quiser alterar o cliente, para ver suas faturas, será feito a seleção no grid de clientes e ao pressionar ‘Select Customer’, o processo começa novamente como vimos na 2da. execução.

E como fazemos para voltar a trabalhar com as faturas de todos os clientes e não de um?O que acontece se o usuário não selecionar nenhum cliente do grid com o mouse e pressionar ‘Select Customer’. O valor da variável &CustomerId fica vazio, pois CustomerId não vai ter valor.

Por este motivo, o botão ‘Select Customer’ poderíamos chamar ‘Select/Unselect’.

Page 359: 93909254 GENEXUS Heuristica Apostila Teorica

359

Web PanelsGrid - Propriedades

• Paginação automática: Se a propriedade Rows possuir um valor diferente de 0 GeneXus realiza a paginação automática

Insere os botões de paginação de forma automática

Os botões inseridos dependem da quantidade de registros e da quantidade de linhas do grid.

Page 360: 93909254 GENEXUS Heuristica Apostila Teorica

360

Web PanelsGrid – Ordem automática das colunas

Não é necessário programar nenhum código adicional para ordenar as colunas: clique sobre o título da coluna.

A página do grid carregado é ordenado, mas não compete com o Order programado no grid.

Esta funcionalidade é válida para grids em transações e web panels.

Page 361: 93909254 GENEXUS Heuristica Apostila Teorica

361

Web PanelsTipos de grids

• Grid stardand: Dados repetitivos no formato fixo (filas e colunas)

• Grid Free Style: Dados repetitivos em formato livre.

• Tabela com registros repetitivos

• As colunas não possuem títulos

• Permite ter mais de um tipo de controle numa mesma célula

Dois tipos de grid:

• Grid padrão: que vimos até agora, em Transações e Web Panels• Grid Free Style

Estes grids, agregam potência ao desenho de aplicações web, permitindo ao desenvolvedor maior liberdade na hora do desenho.

O grid Free Style permite ao usuário definir o formato dos dados a serem mostrados de uma forma menos estruturada que o grid padrão.

O grid Freestyle é basicamente uma tabela que podem inserir os atributos/variáveis, text blocks, imagens, botões, web components, embedded pages, grids freestyle e/ou grids que serão mostrados posteriormente na tela. Neste caso para poder visualizar as propriedades tem que selecionar a tabela onde se encontram os atributos/variáveis.

No exemplo apresentado acima queremos mostrar alguma informação dos países. O atributo CountryFlag foi incluído na transação “Country” para armazenar a foto da bandeira de cada país (é um atributo de tipo Blob). Mas não queremos mostrar a informação como o faríamos em um grid padrão, cada elemento de informação em uma coluna diferente do grid. Aqui queremos mostrar a foto e abaixo o identificador e nome do país.

O comportamento das variáveis dentro de um grid Free Style é análogo ao apresentado dentro de um grid padrão, portanto também são de ingresso se existe um For each line ou For each line in <grid> dentro de algum evento, ou se associa um evento a qualquer controle da fila. Novamente este comportamento pode ser modificado, agregando a regra noaccept ou alterando a propriedade Read Only.

Page 362: 93909254 GENEXUS Heuristica Apostila Teorica

362

Web PanelsMúltiplos grids – Grids aninhados

Exemplo: Mostrar todos os países com seus respectivos clientes, e quantidade de clientes.

Grid1: Free Style.

Grid2: standard

Trn Country

{

CountryId*

CountryName

CountryFlag

}

Trn Customer{

CustomerId*

CustomerName

CustomerAddress

CountryId

CountryName

}

Tabela base Grid1: COUNTRY

Tabela base Grid2: CUSTOMER

Este caso de grids aninhados é igual o de for each aninhados em um procedimento: ou seja, aqui as cargas estão relacionadas, e no Grid2 é carregado todos os clientes pertencentes ao país carregado no Grid1.

A ordem de execução dos eventos estará aninhada:

Refresh (genérico)Grid1.Refresh

Grid1.Load � carga de um paísGrid2.RefreshGrid2.Load � carga de cliente do paísGrid2.Load � carga de cliente do paísGrid2.Load � carga de cliente do país

Grid1.Load � carga do país seguinteGrid2.RefreshGrid2.Load � carga de cliente do paísGrid2.Load � carga de cliente do paísGrid2.Load � carga de cliente do país

.....

Page 363: 93909254 GENEXUS Heuristica Apostila Teorica

363

Web PanelsGrid Free Style

(Exemplo: Continuação)

Propriedades

Grid Free Style

Page 364: 93909254 GENEXUS Heuristica Apostila Teorica

364

Web PanelsTipos

• Tipos de Web panels• Component• Web Page• Master Page

• Propriedade Type

Os objetos web podem ser definidos com três tipos diferentes, configurável na propriedade Type do objeto. Para uma web panel poderá ter um dos valores:

• Component: (transação ou web panel, que a partir daqui poderá ser incluído em outro web object)• Web Page (isto é, o objeto será uma transação ou web panel tal como temos trabalhado até o momento)• Master Page

Em seguida introduziremos a Web Panel tipo: Component”, “Master Page” e sua utilização.

Page 365: 93909254 GENEXUS Heuristica Apostila Teorica

365

Web PanelWeb Component

Já programamos uma web panel ‘CustomerView’ que mostrava os dados do cliente � vamos reutilizar

Um component é uma web panel que éexecutada dentro de outra.

Page 366: 93909254 GENEXUS Heuristica Apostila Teorica

366

Web PanelsWeb Component

Page 367: 93909254 GENEXUS Heuristica Apostila Teorica

367

Web PanelsWeb Components

Exemplo: Criar um novo tab na instância do Pattern Work ‘With Countries, mostrando os clientes de cada país.

1) Definir a Web Panel CustomersPerCountry como Component

2) Definir o novo tab CustomersPerCountry na instância do Pattern Work With Countries

A Web Panel CustomersPerCountry recebe CountryId como parâmetro.

Page 368: 93909254 GENEXUS Heuristica Apostila Teorica

368

Web PanelsWeb Components

Page 369: 93909254 GENEXUS Heuristica Apostila Teorica

369

Web PanelsMaster Pages

Criadas automaticamente com a KB

Controle onde as páginas serão carregadas

As Master Pages fornecem uma forma de centralizar o layout e o comportamento comum em um objeto e reutilizá-lo em qualquer objeto, isso sem termos que programar.

Ter um look&feel consistente é hoje em dia um dever de toda aplicação Web.Criar e manter cada página de uma aplicação Web assegurando a consistência com o resto do site leva grande tempo de programação.

Ao criar uma base de conhecimento GeneXus X criará também dois objetos de tipo Mastet Page:

• ApplMasterPage: Para a aplicação• PromptMasterPage: Para os prompts

Uma web panel, AppMasterPager categorizado como “Master Page” será criada com tudo, ou seja, o Layout e comportamento comum a todas as páginas do site, e no mesmo se deixa um espaço para carregar a página correspondente (o conteúdo variável do site). Corresponde ao controle especial ContentPlaceholder. As páginas web que implementam o conteúdo variável, se implementam como Web Panels ou Web Transactions comuns e correntes (édo tipo “Web Page”, ver página anterior), e se associam a Master Page, de maneira que cada vez que se executem, são carregadas com esse “contexto”. Agora faça o seguinte, abra qualquer objeto GeneXus com form (transação ou web panel) criada na KB, e veja o valor da propriedade Master Page.

As Master Pages fornecem uma forma de centralizar o layout e o comportamento comum em somente um objeto e reutilizá-lo em todo outro objeto sem ter que programar. Isto significa que a modificação de alguma parte do layout ou do comportamento comum é tão fácil como modificá-la num único objeto e pronto!.

Em uma mesma base de conhecimento podem ser definidas tantas Master Pages quanto desejar.

Page 370: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOW

Page 371: 93909254 GENEXUS Heuristica Apostila Teorica

• O que é um workflow?

Um conjunto de tarefas ordenadas em determinada sequencia, que define um processo no qual as situações são resolvidas manualmente ou automaticamente.

• Exemplo

GXFLOWBreve introdução teórica

No exemplo se está mostrando um workflow de uma empresa que vende mercadoria “por atacado”.

Podem ser observados claramente as tarefas consecutivas seguintes para fazer o processo de venda.

Page 372: 93909254 GENEXUS Heuristica Apostila Teorica

• Por que recomendamos incluir tecnologia de workflow dentro de nossas soluções GX?

Porque todo sistema que quisermos construir para uma empresa, 99% terá processos de negócios para modelar, gerenciar e dar seguimento …

- conjuntos de tarefas ordenadas

- responsáveis

- cronogramas, alertas, tempos máximos ...

e gerenciar e dar seguimento: Gxflow faz

GXFLOWBreve introdução teórica

Page 373: 93909254 GENEXUS Heuristica Apostila Teorica

• Gxflow é uma ferramenta integrada a GeneXus que nos permite:

• Modelar os processos da empresa

• Definir segurança

• Definir calendários, alertas, deadlines

• Etapas de Modelado e Desenvolvimento da aplicação operacional integradas

• Etapa de execução que brinda pro-atividade

• Auditoria

• Clareza para capacitar membros novos e para mostrar aos clientes

GXFLOWBreve introdução teórica

Gxflow é uma ferramenta integrada ao GeneXus que nos permite e brinda:

1) Modelar os processos da empresa: Diagramar os processos nos da vantagem de poder mudar a ordem de suas tarefas, tirar ou incluir tarefas novas e/ou mudar as condições de sua execução, sem tocar o código dos mesmos objetos.

2) Definir segurança: Se definem regras e quais podem executar quais tarefas. Isto evita ter que incluir código para a segurança nos objetos.

3) Definir calendários, alertas, deadlines

4) Etapas de Modelado e Desenvolvimento de aplicação operacional integradas: Em GeneXus X émuito prático e simples relacionar os objetos GeneXus desenvolvidos que implementam a aplicação operacional com os diagramas que modelam os processos. Veremos como se arrastam os objetos aos diagramas e a prática resultante em ter modelado os processos integrados com o desenvolvimento da aplicação operacional.

5) Etapa de execução que brinda proatividade: Cada usuário ao executar, de primeira verá as tarefas que precisam ser feitas (não terá que buscar na aplicação o trabalho pendente).

6) Auditoria: GXflow permite ver o que está em cada usuário, quanto tempo leva cada tarefa, etc.

7) Melhor entendimento: para um membro novo da equipe de trabalho, e também para fazer mostras aos clientes.

Page 374: 93909254 GENEXUS Heuristica Apostila Teorica

• Passos para trabalhar com GXflow:

GXFLOWBreve introdução teórica

INTERCALADOS

• Criar objetos GeneXus que descrevem realidade e processos

• Criar diagramas de processos de negócios para modelar os processos

• Associar objetos GeneXus a diagramas de processos de negócios

• Executar processo

Page 375: 93909254 GENEXUS Heuristica Apostila Teorica

• Como criar um diagrama de processo de negócio?

Criando um objeto na KB de tipo Business Process Diagram

• Quantos diagramas de processos de negócios definiremos em nossa KB?

A quantidade de processos que tenham na empresa

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

Page 376: 93909254 GENEXUS Heuristica Apostila Teorica

• Definição passo a passo.. (1)

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

Page 377: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

• Definição passo a passo.. (2)

ARRASTANDO ESTES SÍMBOLOS ÉCONFECCIONADO O DIAGRAMA

TAREFA / ATIVIDADE INTERATIVA

TAMBÉM SE PODE ARRASTAR AO DIAGRAMA TAREfA / ATIVIDADE INTERATIVA A PARTIR “FOLDER VIEW”

A partir do “Folder View” se arrasta um objeto transação ou web panel ao diagrama, se estaráagregando una “tarefa / atividade interativa” ao fluxo, e a mesma já ficará com dito objeto associado para a etapa de execução. Também dita “tarefa / atividade interativa” agregada ao diagrama, ficará automaticamente nominada com o mesmo nome que a transação ou web panel que foi arrastado.

Por outro lado se agregar uma “tarefa/atividade interativa” ao diagrama arrastando o símbolo correspondente a partir do toolbox disponível para confeccionar diagramas de processos de negócios, depois será necessário associar a dita tarefa um objeto transação ou web panel definida na KB. Para isso, simplesmente de ter agregado a tarefa no diagrama e a tendo selecionada, terá que editar suas propriedades (F4 para abrir o diálogo de propriedades) e completar a propriedade Web Application com o objeto que corresponda, assim como a propriedade Name com o nome que se queira dar a “tarefa/atividade interativa”.

Page 378: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

• Descrição de símbolos

INÍCIO DE PROCESSO

ATIVIDADE/TAREFA INTERATIVA

ATIVIDADE/TAREFA BATCH

FIM DO PROCESSO

NESTE PROCESSO QUE SE ESTÁ MODELANDO, OUTRO PROCESSO É REUTILIZÁVEL COMO SUBRPROCESSO

CONDIÇÃO PARA AVALIAR… E DEPENDENDO DO RESULTADO, SEGUIRÁ UMA ROTA OU OUTRA

VÁRIAS ROTAS CHEGAM ATÉ ESTE SÍMBOLO E ASSIM QUE TODAS CHEGUEM A ESTE PONTO, O FLUXO CONTINUA

Não serão descritos todos os símbolos disponíveis na toolbox de workflow, mas sim os símbolos básicos que no início devemos conhecer.

Símbolo: Condição

Quando se está modelando um diagrama de processo e em determinada parte do fluxo de atividades se necessita avaliar uma condição porque dependendo dela ser cumprida ou não, siga com certo fluxo de atividades ou outro, por isso que contamos com o símbolo de condição.

Page 379: 93909254 GENEXUS Heuristica Apostila Teorica

Bastará agregar um símbolo de condição (losango verde) ao diagrama (conectado desde a atividade prévia) e a partir do losango poderão sair N rotas (que terão a cor verde também). Cada uma destas rotas verdes que partem de um losango de condição, deverá ter associada uma condição a ser avaliada (fazendo clique duplo em cada rota verde, um editor é aberto para ingressar sua condição associada); e em tempo de execução do diagrama, como veremos mais adiante, quando se chegue a condição na execução do processo, dependendo de quais avaliações for verdadeira continua com a execução de uma rota e seu fluxo de atividades segue, ou outro.

Em breve veremos exemplos de definição de condições (sintaxe e possibilidades).

Símbolo: Batch Activity

Permite agregar a um diagrama de processo de negócio, um processo batch (por exemplo um processo maciço) que será executado no servidor.

É agregado arrastando o símbolo correspondente desde a toolbox, depois será necessário associar a dito processo batch um objeto procedimento definido na KB. Para isso, simplesmente depois de ter agregado o símbolo de processo batch no diagrama e tendo selecionado, terá que editar suas propriedades (F4 para abrir o diálogo de propriedades) e completar na propriedade Procedure o nome do procedimento que corresponda. Assim mesmo terá que atribuir um nome em sua propriedade Name.

Se por outro lado a partir do “Folder View” se arrasta um determinado procedimento, estará sendo agregado ao diagrama como processo batch que executará no servidor; e o mesmo já ficará com dito procedimento e nome associado para a etapa de execução.

Page 380: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

• Definição passo a passo.. (3)

O diagrama de processo de negócio vai sendo confeccionado, arrastando símbolos de Toolbox e objetos de Folder View ….

QUE INFORMAÇÃO PODEMOS ENVOLVER NAS CONDIÇÕES?

Aqui vemos que temos confeccionado o diagrama de processo que criamos. Temos agregado tarefas interativas e uma condição.

Vemos que com um duplo clique nas rotas verdes que partam da condição, se abre o editor de condições para editar cada condição (em caso dela se cumprir uma ou outra se seguirácom certo fluxo de atividades ou outro).

Em seguida veremos o conceito de “Dados Relevantes” que é fundamental para compreender qual informação podemos envolver nas condições.

Page 381: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

• Conceito fundamental: Dados Relevantes

• O conceito de “Dados Relevantes” se utiliza para manter uma área global de dados num processo

• Este conceito permite administrar a passagem de informação entre as tarefas e que a informação seja conhecida em todo o fluxo

• As “variáveis globais” podem ser vistas como são no processo

TODO “DIAGRAMA DE PROCESSO DE NEGÓCIO” TEM UM TAB PARA A DEFINIÇÃO DE SEUS DADOS RELEVANTES

Page 382: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

• Conceito fundamental: Dados Relevantes (Cont.)

• Quando se arrasta a partir do “Folder View” uma transação a um diagrama de processo, automaticamente se cria um dado relevante com o mesmo nome e mesmo tipo de dado que a chave primária da transação:

• Também definiremos dados relevantes explicitamente, como veremos..

AO ARRASTAR A TRANSAÇÃO “INVOICE” AO DIAGRAMA, AUTOMATICAMENTE ESTE DADO RELEVANTE FOI CRIADO

NOSSO OBJETO DE TIPO “BUSINESS PROCESS MODEL”

Quando são definidos dados relevantes em um diagrama de processo (definidos automaticamente ou definidos explicitamente) algo a ser dito é que não são os mesmos atributos definidos na KB.

A sintaxe do nome de um dado relevante definido em um diagrama de processo, é totalmente análoga a sintaxe do nome de um atributo (e além disso tem um tipo de dados associado)...mas não é um atributo, mas sim um “dado global” que será conhecido em todo esse diagrama de processo.

Ou seja que ao ver num diagrama de processo um dado relevante de nome InvoiceId, não devemos confundir com o atributo definido na KB.

Todavia, para os dados relevantes que são definidos automaticamente com mesmo nome e tipo que as chaves primárias das transações (como neste exemplo: InvoiceId), tem uma correspondência automática entre o dado relevante e o atributo PK, no sentido que quando modelamos o diagrama “o dado relevante é o dado global conhecido nesse contexto” e nos objetos GeneXus que desenvolvemos as atividades do diagrama “recebemos no parm o atributo PK” (tratando-se da mesma informação ou no contexto do diagrama, ou no contexto do desenvolvimento da funcionalidade respectivamente). Em outras palavras tem um mapa automático entre o dado relevante com o mesmo nome e tipo que um atributo chave primária com dito atributo chave primária.

A maioria de Dados Relevantes num diagrama de processo se correspondem com as chaves primárias, também existem casos que surge a necessidade de definir explicitamente outros dados relevantes. Em seguida veremos exemplos, e também veremos como definir correspondência entre dados relevantes que definiremos em um diagrama de processo e variáveis que deveremos definir nos objetos GeneXus associados as atividades do diagrama (veremos que utilizaremos tipos de dados workflow, propriedades e métodos, para que variáveis “a nível de objeto” correspondam com dados relevantes definidos “a nível do diagrama de processo”).

Page 383: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

• Quando surge a necessidade de definir dados relevantes?

Trn “Invoice”

Web Panel “Authorization”

Parm(InvoiceId);

COMO CARREGO UM VALOR OU OUTRO NESTES EVENTOS E QUE O VALOR CARREGADO “SEJA VISTO” NO DIAGRAMA PARA AVALIAR CONDIÇÃO POSTERIOR?

InvoiceId = Dado Relevanteno diagrama

Inicialmente explicamos que quando trabalhamos no GeneXus com workflow, realizamos basicamente os seguintes passos:

• Criar objetos GeneXus

• Criar diagramas de processos de negócios

• Associar objetos GeneXus a diagramas de processos de negócios

• Executar processo

Estamos assim confeccionando um diagrama de processo em nossa KB; tínhamos previamente definidos alguns objetos GeneXus que arrastamos ao diagrama, e vamos desenvolvendo outros objetos e incorporá-los ao diagrama também. Mais adiante veremos como atribuir regras as diferentes atividades do diagrama. Por enquanto a idéia é que contamos na KB com uma transação “Invoice”, a qual foi arrastada ao diagrama como primeira atividade interativa do processo e mais adiante definiremos que esta tarefa interativa poderá ser executada pelas vendedoras da empresa.

Quando uma vendedora ingresse uma venda (através da transação “Invoice”), entrará o cliente, a mercadoria solicitada, as quantidades, a forma de pagamento solicitada pelo cliente, gravará a venda com um número interno (não o nro da fatura formal) e aí terminará a primeira atividade. Depois essa venda deverá ser avaliada por um supervisor (quem vai avaliar de qual cliente se trata, o montante, a forma de pagamento), e o supervisor deverá aceitar ou recusar a venda. Esta segunda atividade interativa do processo foi agregada ao diagrama arrastando a web panel “Authorization”.

Então, a nível do diagrama de processo contamos com o dado relevante InvoiceId (com o mesmo nome e tipo de dado que o atributo InvoiceId), o qual significa que dito dado se conhece ao longo de todo o fluxo de atividades. E no que se refere aos objetos GeneXus relacionados ao diagrama, a web panel “Authorization”implementa a 2da atividade do processo e recebe por parâmetro o atributo InvoiceId. No form da web panel “Authorization” serão visualizados os dados da fatura, o limite de crédito e o saldo do limite de crédito do cliente e possibilita ter o histórico das faturas anteriores do cliente. Esta web panel oferecerá ao supervisor 2 botões: “Authorize” e “Refuse”.

Page 384: 93909254 GENEXUS Heuristica Apostila Teorica

Vale explicar que quando trabalhamos com workflow em GeneXus, no código dos objetos já não podemos chamar de um objeto a outro. Por outro lado, nos diagramas de processos que confeccionamos já ficam implícitas as chamadas entre atividades consecutivas.

Mais adiante veremos que na etapa de execução vamos executar uma aplicação que nos permite criar instancias dos processo que definimos (por exemplo poderão ser criadas N instancias do processo de venda definido). Ao criar uma nova instancia de processo, começa a execução da primeira atividade (será mostrada a trn “Invoice” para isso, e se foram definidas, será validado que em particular essa atividade seja realizada por uma vendedora, seguirá a segunda atividade (para ser efetuada por ele rol que corresponda, que em nosso exemplo é um supervisor) e assim sucessivamente e as atividades da instancia do processo vão sendo finalizadas e executando as seguintes atividades até concluir dita instancia do processo.

De modo que não codificamos mais calls nos objetos GeneXus, e caso se necessite mudar a ordem de precedências das atividades em um processo, ou agregar ou tirar atividades, assim como mudar as condições de execução das atividades, fazemos no diagrama de processo sem tocar o código dos objetos no diagrama de processo.

Algo que se deve notar é que não definimos calls no código mesmo dos objetos, mas definimos regra parm nos objetos, se definimos a regra parm nos objetos GeneXus que participam num diagrama de processo. Isto éporque os objetos são chamados – com outro esquema de trabalho do que conhecíamos – e precisa passar a informação necessária ... Assim é que são recebidos por parâmetro os atributos chaves primárias que são análogas aos dados relevantes no diagrama de processo (e que tem uma correspondência entre esses conceitos).

Agora que isso foi explicado, seguiremos estudando passo a passo a implementação da segunda atividade do processo que estamos confeccionando. A web panel “Authorization” recebe por parâmetro o atributo InvoiceId,

que mostra em seu form informação para a tomada de decisão da autorização ou recusa e para isso tem 2 botões “Authorize” e “Refuse” respectivamente.

Se nosso objetivo é carregar uma variável com valor 1 no evento “Authorize” e com valor 0 no evento “Refuse”, e queremos que o valor atribuído “seja visto” no diagrama de processo, bastará realizar o seguinte:

1) No tab “Relevant Data” do diagrama de processo, precisa criar um dado relevante (por exemplo de nome: InvoiceAuthorized) de tipo Numeric.

2) Na web panel "Authorization“ terá que ler o dado relevante e carregá-lo em cada evento da web panel, assim:

Sendo:

&wfAuthoriz: uma variável definida na web panel, de tipo de dados é: WorkflowApplicationData

&wfProcessInstance: uma variável definida na web panel, de tipo de dados:

WorkflowProcessInstance

Page 385: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

1)

Em wbp “Authorization”definimos 2 variáveis de tipos de dadosWorkflowApplicationDatae WorkflowProcessInstancepara ler e carregar o dadorelevante

• Definição passo a passo.. (4)

Criação explícita de Dado Relevante no Diagrama de Processoe como trabalhar com o mesmo nos objetos

2)

Vimos que definimos um dado relevante no diagrama de processo (de nome InvoiceAuthorized) e depois na web panel “Authorization” se lê o dado relevante na variável &wfAuthoriz de tipo WorkflowApplicationData. O tipo de dados WorkflowApplicationData significa “dado relevante”.

Também temos definido na web panel uma segunda variável de tipo WorkflowProcessInstance. O tipo de dados WorkflowProcessInstance significa “instancia de processo”. Ou seja se analisarmos a primeira linha codificada dos 2 eventos, estamos recuperando na variável &wfAuthoriz (de tipo “dado relevante”) o valor do dado relevante de nome ‘InvoiceAuthorized’ (entre aspas vai o nome do dado relevante tal como foi definidono diagrama de processo) pertencente a instancia do processo que está sendo executado.

Depois na segunda linha codificada em ambos eventos, se está atribuindo a variável &wfAuthoriz (de tipo “dado relevante”) o valor 0 ou 1 segunda corresponda (utilizando a propriedade Numeric do tipo de dado WorkflowApplicationData, por estar atribuindo um valor numérico).

Por último em cada evento se faz return, porque já foi recuperado o valor do dado relevante, se foi carregado o valor desejado e se deseja culminar com a execução desta atividade.

Desta maneira então lemos e carregamos dados relevantes nos objetos GeneXus associados as atividades de um diagrama de processo (exceto quando se trata de dados relevantes com mesmo nome e tipo que as chaves primárias, já que nesses casos são recebidos por parm os atributos primários diretamente e pronto).

Page 386: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

Em todo o diagrama contamos com o Dado Relevante InvoiceAuthorized...

Em rotas que saem da condiçãoSe avalia o valor do dado RelevanteInvoiceAuthorized…

• Definição passo a passo.. (5)

Avaliação de Dado Relevante em condição de Diagrama de Processo

Page 387: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

• Outra solução possível para resolver passos (4) e (5)

1) Se quiser definir atributo InvoiceAuthorized na trn “Invoice” e gravar em cada invoice se foi autorizado ou não..

2) Na web panel “Authorization” se chama proc em cada evento, que grava 1 ou 0 no atributo InvoiceAuthorized da invoice autorizada/recusada

3) No Diagrama de Processo o atributo InvoiceAuthorized pode ser inferido (através de Dado Relevante InvoiceId que corresponde ao atributo InvoiceId) a avaliamos diretamente dito atributo

AVALIAMOS ATRIBUTO

(NÃO DADO RELEVANTE)

Com esta solução, não temos necessidade de definir Dado Relevante InvoiceAuthorized, já que temos num atributo a informação se a invoice foi autorizada/recusada… e no fluxo podem ser inferidos atributos através dos Dados Relevantes correspondentes a chaves primárias, e avaliar diretamente atributos.

Page 388: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

• Definição de regras

1)

2)

DEFINIÇÃO DE REGRAS NA KB

ATRIBUIÇÃO DE REGRAS DAS ATIVIDADES NO DIAGRAMA

A definição de regras a nível da KB na seção de Preferences.

Depois selecionando cada atividade do diagrama e pressionando F4, na propriedade Roles poderá atribuir a lista de regras que dita atividade poderá executar.

Page 389: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

• Diagrama de Processo completo correspondente ao processo que estamos confeccionando:

Se o supervisor autoriza uma venda, a seguinte atividade no diagrama é “InvoiceToBePrepared”. Esta atividade interativa tem uma web panel associada que recebe por parâmetro o atributo InvoiceId, mostra a informação da venda autorizada e tem um botão para que a pessoa do pacote quando terminar de preparar a mercadoria o pressione. O evento associado a esse botão, vai chamar um procedimento que gravará num atributo da invoice, um valor indicador (flag) de que o pacote já foi realizado.

A seguinte atividade é interativa e tem uma panel associada que recebe por parâmetro o atributo InvoiceId, mostra a informação da venda preparada e tem um botão para emitir a fatura. Quando uma vendedora pressionar este botão, o evento associado ao botão chama um procedimento que grava na invoice o número de fatura formal e emitirá a impressão.

A última atividade deste fluxo que estamos explicando, corresponde a distribuição da mercadoria. Esta atividade também tem uma web panel associada que mostra os dados da venda e pressionando um botão, uma proc grava que a mesma foi entregue.

As datas/horários que foram efetuadas cada uma das atividades, ficarão registradas durante a execução do workflow.

Page 390: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

• Passos para executar:

• Save All • Build All• (Serão solicitados dados de Enviroment)• Run do Diagrama de Processo

Page 391: 93909254 GENEXUS Heuristica Apostila Teorica

GXFLOWConceitos básicos para criar

diagramas de processos de negócios

• Execução:

Tem 2 modalidades de execução:

• Prototyper• Full Client

Na seção de Preferences se configura a desejada:

Logicamente a modalidade “Prototyper” está orientada a etapa de prototipação. E a modalidade “Full-Client” a etapa de produção.

Na etapa de prototipação não nos interessa testar a segurança, motivo pelo qual ao executar a aplicação na modalidade “Prototyper” inicialmente são limpas todas as instancias de testes anteriores e épermitido executar todas as atividades sem controlar regras.

Ao executar a aplicação na modalidade “Full-Client”, não se aborta nada inicialmente e se requer criar usuários (para login) cada um deles com a lista de regras que o corresponda, já que neste caso a segurança é controlada.

Page 392: 93909254 GENEXUS Heuristica Apostila Teorica

GERÊNCIA DE VERSÕES

Page 393: 93909254 GENEXUS Heuristica Apostila Teorica

Gerência de VersõesO desenvolvimento de software é um trabalho em equipe e certo grau de confusão é inevitável.

Não pode reproduzir o error nesta versão!

Este programa ontem

funcionava!

O que aconteceu com a regra da

semana passada?Realmente estamos

trabalhando na última versão?

A aplicação em execução não écompatível com o

código fonte

Page 394: 93909254 GENEXUS Heuristica Apostila Teorica

Gerência de VersõesConclusão:

• O ciclo de desenvolvimento é um processo dinâmico que requer controle das alterações realizados aos objetos do projeto.

Se necessita:

• Marcar marcos no desenvolvimento da aplicação

• Ter linhas de desenvolvimento paralelas

• Administrar o ciclo de vida da aplicação (SCM)

KBVersão 1 Versão 2 Versão N

. . .

Durante o processo de construção da aplicação, é necessário marcar marcos no desenvolvimento da mesma, entendendo como marcos o “congelamento” do desenvolvimento num determinado momento especial no processo. Isto pode acontecer por exemplo para liberar uma versão na produção, congelar uma versão entregue a um cliente, a necessidade de congelar um determinado estado especial da aplicação, etc.

Além disso também vamos querer ter diferentes linhas de desenvolvimento da aplicação, algo muito comum por exemplo quando se quer fazer variações do projeto para um cliente ou quando se requer que dois grupos de trabalho o façam em paralelo e necessitamos poder realizar uma administração de todos estes elementos.

O que necessitamos basicamente é administrar o “ciclo de vida” da aplicação durante o desenvolvimento. Várias destas funcionalidades entram no que no mundo do software se conhece como SCM (Software Configuración Management)

Page 395: 93909254 GENEXUS Heuristica Apostila Teorica

Solução: Gerência de versões da aplicação

Nó raiz da árvore de versões

APPAPP 1.0 1.1 1.2 2.0

1.1.1

1.0.1

2.1

1.1.2

1.0.1 1.0.2

Gerência de Versões

Começa o desenvolvimento seguindo uma linha principal de desenvolvimento (linha do meio – Trunk), lugar onde são agregadas as funcionalidades requeridas e são utilizados protótipos para prová-las .

Em determinados momentos deste ciclo surge a necessidade de estabelecer um checkpoint no processo, seja pela liberação de uma versão, a entrega de uma versão a um cliente, a necessidade de congelar um determinado estado de uma aplicação, etc. Então o que fazemos é congelar o produto nesse momento criando por exemplo a versão 1.0 que a entregamos a um cliente e continua o processo de desenvolvimento principal.

Em determinado momento surge a necessidade de realizar correções sobre a versão entregue ao cliente (1.0) sendo necessário abrir uma nova linha de desenvolvimento para incluir estas correções sobre o que era a versão 1.0 sem afetar a linha de desenvolvimento principal que continuou crescendo desde o momento que foi congelada a versão 1.0.Então se cria o que se conhece como Developmen Version ou branch, que é simplesmente uma nova linha de desenvolvimento paralela a principal.

Depois durante o transcurso do projeto voltam a aparecer requerimentos deste tipo, seja pela determinação de checkpoints como a necessidade de abrir novas linhas de desenvolvimento, então por exemplo criamos a versão 1.1, ou a 1.0.1 que vem a ser um congelamento da linha de desenvolvimento aberta a partir da versão 1.0 e assim sucessivamente até ter por exemplo a situação estabelecida no diagrama.

Estas situações formam parte da operação normal no desenvolvimento de uma aplicação e é necessário administrar este processo de forma fácil..Para isso se introduz o conceito de Gerência de Versões. As versões são classificadas em:

•Development Versions, representam as linhas de desenvolvimento da aplicação as quais são independentes entre si, existe uma linha principal e várias paralelas, a principal vem a ser o que se conhece como Trunk e as demais seriam o que em SCM se conhece como Branches•Frozen Versions (também conhecidas como Labels em SCM), representam as congeladas criados em determinados momentos do processo sobre as DV para determinar certos checkpoints (liberação de versão, entrega ao cliente, congelar estado, etc.)

Page 396: 93909254 GENEXUS Heuristica Apostila Teorica

Solução: Gerência de versões da aplicação

Nó raiz da árvore de versões

APPAPP

Frozen VersionsDevelopment Version

1.0 1.1 1.2 2.0

1.1.1

1.0.1

2.1

1.1.2

1.0.1 1.0.2

Development Version

Gerência de Versões

Development Version (Trunk)

Page 397: 93909254 GENEXUS Heuristica Apostila Teorica

APPAPP

Development Version

1.0 1.1 1.2 2.0

1.1.1

1.0.1

2.1

1.1.2

1.0.1 1.0.2

Development Version

Gerência de Versões

Development Version principal (Trunk)

Nó raiz da árvore de versões = nó raiz do Trunk

As development version são as linhas de desenvolvimento da aplicação, isto é o lugar onde efetivamente criamos e modificamos a aplicação.

No ciclo de vida de uma aplicação participa uma linha de desenvolvimento principal, isto é, onde começa o processo de desenvolvimento da aplicação e na qual normalmente se vai estar fazendo as modificações requeridas no avanço do projeto. Em SCM esta linha de desenvolvimento é conhecida com o nome de Trunk.

Além desta linha principal poderão existir uma ou várias linhas de desenvolvimento secundárias, totalmente independentes da linha principal e independentes entre si. Em SCM estas linhas de desenvolvimento secundárias são conhecidas como Branches e são usadas em geral para realizar correções ou pequenas alterações sobre versões congeladas ou liberadas da aplicação, ou para liberar uma versão especial para um cliente.

O desenvolvimento em cada uma destas development version é independente, tendo cada versão seus próprios objetos, sua própria base de dados, ambientes para gerar a aplicação, etc.

Uma Development Version, é então, uma cópia da KB editável e independente.

Page 398: 93909254 GENEXUS Heuristica Apostila Teorica

Frozen Version: Versão não modificável, é uma “foto” da aplicação num dado momento.

Gerência de Versões

APPAPP

Frozen Versions

1.0 1.1 1.2 2.0

1.1.1

1.0.1

2.1

1.1.2

1.0.1 1.0.2

Uma Frozen Version permite armazenar de forma estática momentos especiais da KB. É o elemento que utilizamos para marcar distintos marcos no processo, como por exemplo “feche” uma versão para liberá-la aos clientes.

Se obtêm a partir de uma versão em desenvolvimento (development version), “congelando-a” para obter uma “foto” num determinado momento.

A versão obtida é Read Only, que objetos da mesma não poderão ser modificados, nem tampouco suas propriedades. Sendo possível realizar ações relacionadas com a geração da aplicação, como por exemplo a criação da base de dados ou a geração novamente dos programas.

Quando congelamos uma versão é porque determinamos que a mesma está em um estado consistente e seria conveniente guardar dito estado. Por exemplo, congelamos uma version X para se dar aos clientes, em determinado momento, enquanto o processo de desenvolvimento continua, um novo cliente requer a aplicação, então o que fazermos é gerar a mesma na version X, que sabemos que tem um estado correto e a instalamos ao novo cliente.

Se os objetos não poder ser modificados, podem ser abertos para distintas consultas ou para realizar comparações com outras versões da aplicação.

Page 399: 93909254 GENEXUS Heuristica Apostila Teorica

APPAPP …..

Variações devido a consertos ou alterações dos requerimentos

Development Version

“principal”(Trunk)

Ciclo de desenvolvimento principal - Prototipado

Gerência de Versões

Exemplo de versões: Implementação passo a passo

Partimos do nó raiz da árvore de versões, o qual se cria ao criar a KB.A aplicação vai sofrendo alterações a medida que transcorre o ciclo de desenvolvimento. A linha de desenvolvimento principal é onde se implementam as funcionalidades requeridas e onde se faz a prototipação.Esta linha de desenvolvimento geralmente coincide com o Trunk, ou seja com a ramo principal da árvore de versões. É uma Development Version criada por default quando a KB é criada.A medida que as modificações na aplicação são realizadas, a mesma vai se alterando ao longo do tempo.

Page 400: 93909254 GENEXUS Heuristica Apostila Teorica

Nó raiz da árvore de versões = nó raiz do Trunk

Gerência de VersõesPara ver a árvore de versões, abrimos a janela Knowledge Base

Versions (View/Versions):

Page 401: 93909254 GENEXUS Heuristica Apostila Teorica

APPAPP ….. Development Version “principal” (Trunk)

1.01.0 Frozen Version 1.0

Gerência de Versões

Surge a necessidade de “congelar” versões, para fixar marcos no projeto. Para isso criamos Frozen Versions (cópia somente de leitura da aplicação).

As Frozen Version servem para:

• Analisar (não modificar) objetos, propriedades, environments, etc. • Como fonte de um Reporte de Análise de Impacto da base de dados• Para criar a base de dados • Para regerar todos os programas

Page 402: 93909254 GENEXUS Heuristica Apostila Teorica

Botão direito sobre o nó raiz do Trunk e selecionamos Freeze

Gerência de VersõesComo “congelamos” uma Development Version, para criar uma

Frozen Version?

Page 403: 93909254 GENEXUS Heuristica Apostila Teorica

APPAPP ….. Development Version “principal” (Trunk)

1.01.0 1.11.1

Release1Release1

Development Version para “Produção”

Gerência de Versões

Agora queremos colocar a aplicação em Produção. Para isso criamos uma Frozen Version 1.1 e a partir dela criamos uma Development Version “Release 1”.

Na versão de “Produção” vão sendo produzidas variações devido aos consertos, mas não se agrega funcionalidades novas. As mesmas são agregadas na linha de desenvolvimento principal.

As Development Version servem para:- Trabalhar numa linha de desenvolvimento paralela a principal- Como fonte ou destino de uma operation de Revert a partir de uma Frozen Version de Backup

Page 404: 93909254 GENEXUS Heuristica Apostila Teorica

Frozen Version

1.1

Botão direito sobre o nó raiz e click em Freeze

Gerência de VersõesCriamos a Frozen Version 1.1 como vimos anteriormente …

Observe que as Frozen Version mais novas, são mostradas mais acima na árvore de versões.

Page 405: 93909254 GENEXUS Heuristica Apostila Teorica

Development Version

Release1

Gerência de VersõesDepois com botão direito sobre a FV 1.1 e selecionamos New

Version.

O tempo que se demora em criar uma nova Development Version é proporcional ao tamanho da KB.

Page 406: 93909254 GENEXUS Heuristica Apostila Teorica

1.1.11.1.1 1.1.21.1.2Frozen Versions

de Produção

KB1KB1 ….. Trunk

1.01.0 1.11.1 1.21.2 2.02.0 2.12.1

Release1Release1

Gerência de VersõesTambém podemos criar novas Frozen Versions tanto no ramo do

desenvolvimento principal como no ramo de Produção.

Produção

Como as linhas de desenvolvimento do Trunk (Desenvolvimento) e de Relase 1 (Produção) são paralelas, as alterações numa não afeta a outra.

Ambas versões são totalmente independentes e podemos requerer congelá-las por diferentes motivos. Por exemplo, no caso do ramo de Produção, para fixar um estado depois de certos consertos que tivemos que fazer.

De acordo com a metodologia adotada, no ciclo de desenvolvimento principal, é onde se agregam novas funcionalidades, consertos, alterações importantes na aplicação, prototipação e testing. É mais frequente que seja necessária “fotos” nessa etapa viva do desenvolvimento da aplicação.

No ramo do Release1, as alterações são menores, mais certos consertos circunstanciais que não agregam funcionalidade. Neste caso, émenos frequente a necessidade de criar Frozen Versions, mas pode ser igualmente necessário.

Page 407: 93909254 GENEXUS Heuristica Apostila Teorica

Gerência de VersõesObserve que as Frozen Versions mais novas, são mostradas mais

acima na árvores de versões

Page 408: 93909254 GENEXUS Heuristica Apostila Teorica

Botão direito sobre o nóRelease1 e escolhemos “Set Active”

Gerência de Versões

Depois de certos consertos na Produção, nos interessa gerar a aplicação. Para isso marcamos a DV Release 1 como ativa.

GeneXus gera automaticamente os programas e as estruturas da BD, partindo da versão que esteja ativa.

Se pode marcar como ativa uma versão em desenvolvimento ou uma versão congelada. Neste último caso, não poderemos fazer nenhuma modificação a mesma, somente utilizá-la para gerar a aplicação ou para realizar um impacto na base de dados, ou para comparar versões.

Somente pode ter uma versão ativa por vez.

Page 409: 93909254 GENEXUS Heuristica Apostila Teorica

A Development Version que estiver ativa, será utilizada para gerar a aplicação ao fazer um Build (F5)

GeneXus nos indica qual é o ramo ativo

Gerência de Versões