SlideShare uma empresa Scribd logo
1 de 26
Baixar para ler offline
267
268
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.
269
270
271
272
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.
273
274
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.
275
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.
276
277
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).
278
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.
279
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.
280
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).
281
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 commitautomático.
282
283
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]
{
regla1;
regla2;
...
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].
284
285
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.
286
Vamos supor que temos o seguinte diagrama de Bachman genérico:
E no Source de um procedimento fazemos:
For each
C = &C
E = &E
D = &D
Endfor
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.
287
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.
288
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 each
where InvoiceDate <=&date
For each
defined by InvoiceDetailQuantity
DELETE // se eliminam as linhas
Endfor
DELETE //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).
289
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.
290
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.
291
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.
292
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 each
where InvoiceDate >= &startDate
where InvoiceDate <= &endDate
where 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.

Mais conteúdo relacionado

Semelhante a Atualização de dados em GeneXus

05 ordem execucaoregrase-formulas-cursogxxbr
05 ordem execucaoregrase-formulas-cursogxxbr05 ordem execucaoregrase-formulas-cursogxxbr
05 ordem execucaoregrase-formulas-cursogxxbrCristiano Rafael Steffens
 
Cadastro de clientes em c#
Cadastro de clientes em c#Cadastro de clientes em c#
Cadastro de clientes em c#André Luiz
 
Es 02 desenvolvimento de software dirigido por casos de uso - parte i
Es 02   desenvolvimento de software dirigido por casos de uso - parte iEs 02   desenvolvimento de software dirigido por casos de uso - parte i
Es 02 desenvolvimento de software dirigido por casos de uso - parte iRodrigo Gomes da Silva
 
Gestão Contábil - Novo Modelo do Backoffice 11.40
Gestão Contábil - Novo Modelo do Backoffice 11.40Gestão Contábil - Novo Modelo do Backoffice 11.40
Gestão Contábil - Novo Modelo do Backoffice 11.40TOTVS Connect
 
Manual winthor parametrização contábil
Manual winthor   parametrização contábilManual winthor   parametrização contábil
Manual winthor parametrização contábilEvandro Felicio.'.
 
Apostila de Crystal Report
Apostila de Crystal ReportApostila de Crystal Report
Apostila de Crystal ReportAndre Nascimento
 
Cadastro de clientes em java no netbeans
Cadastro de clientes em java no netbeansCadastro de clientes em java no netbeans
Cadastro de clientes em java no netbeansLaurindo Carinhas
 
000047 como fazer totvs - v 4.0.0 - entenda o rm conversor de classis para ...
000047   como fazer totvs - v 4.0.0 - entenda o rm conversor de classis para ...000047   como fazer totvs - v 4.0.0 - entenda o rm conversor de classis para ...
000047 como fazer totvs - v 4.0.0 - entenda o rm conversor de classis para ...kdimmg
 
Curso suporte nivel basico - quais as diferenças entre servidor, pdv e reta...
Curso suporte   nivel basico - quais as diferenças entre servidor, pdv e reta...Curso suporte   nivel basico - quais as diferenças entre servidor, pdv e reta...
Curso suporte nivel basico - quais as diferenças entre servidor, pdv e reta...Lourival Domingues Junior
 
Guia Passo a Passo_ Como Criar uma Conta de Serviç... - ServiceNow Community.pdf
Guia Passo a Passo_ Como Criar uma Conta de Serviç... - ServiceNow Community.pdfGuia Passo a Passo_ Como Criar uma Conta de Serviç... - ServiceNow Community.pdf
Guia Passo a Passo_ Como Criar uma Conta de Serviç... - ServiceNow Community.pdfTiago Macul
 
[SAP BW] Process Chain with Invalid Character
[SAP BW] Process Chain with Invalid Character[SAP BW] Process Chain with Invalid Character
[SAP BW] Process Chain with Invalid CharacterMarcos André
 

Semelhante a Atualização de dados em GeneXus (20)

05 ordem execucaoregrase-formulas-cursogxxbr
05 ordem execucaoregrase-formulas-cursogxxbr05 ordem execucaoregrase-formulas-cursogxxbr
05 ordem execucaoregrase-formulas-cursogxxbr
 
11 data providers-cursogxxbr
11 data providers-cursogxxbr11 data providers-cursogxxbr
11 data providers-cursogxxbr
 
Cadastro de clientes em c#
Cadastro de clientes em c#Cadastro de clientes em c#
Cadastro de clientes em c#
 
10 sd ts-curso-gxxbr
10 sd ts-curso-gxxbr10 sd ts-curso-gxxbr
10 sd ts-curso-gxxbr
 
14 patterns-curso gxxbr
14 patterns-curso gxxbr14 patterns-curso gxxbr
14 patterns-curso gxxbr
 
16 gx flow-curso-gxxbr
16 gx flow-curso-gxxbr16 gx flow-curso-gxxbr
16 gx flow-curso-gxxbr
 
Daw slide 06
Daw slide 06Daw slide 06
Daw slide 06
 
CBT_SD.pdf
CBT_SD.pdfCBT_SD.pdf
CBT_SD.pdf
 
Es 02 desenvolvimento de software dirigido por casos de uso - parte i
Es 02   desenvolvimento de software dirigido por casos de uso - parte iEs 02   desenvolvimento de software dirigido por casos de uso - parte i
Es 02 desenvolvimento de software dirigido por casos de uso - parte i
 
Gestão Contábil - Novo Modelo do Backoffice 11.40
Gestão Contábil - Novo Modelo do Backoffice 11.40Gestão Contábil - Novo Modelo do Backoffice 11.40
Gestão Contábil - Novo Modelo do Backoffice 11.40
 
Manual winthor parametrização contábil
Manual winthor   parametrização contábilManual winthor   parametrização contábil
Manual winthor parametrização contábil
 
Apostila de Crystal Report
Apostila de Crystal ReportApostila de Crystal Report
Apostila de Crystal Report
 
Cadastro de clientes em java no netbeans
Cadastro de clientes em java no netbeansCadastro de clientes em java no netbeans
Cadastro de clientes em java no netbeans
 
000047 como fazer totvs - v 4.0.0 - entenda o rm conversor de classis para ...
000047   como fazer totvs - v 4.0.0 - entenda o rm conversor de classis para ...000047   como fazer totvs - v 4.0.0 - entenda o rm conversor de classis para ...
000047 como fazer totvs - v 4.0.0 - entenda o rm conversor de classis para ...
 
Curso suporte nivel basico - quais as diferenças entre servidor, pdv e reta...
Curso suporte   nivel basico - quais as diferenças entre servidor, pdv e reta...Curso suporte   nivel basico - quais as diferenças entre servidor, pdv e reta...
Curso suporte nivel basico - quais as diferenças entre servidor, pdv e reta...
 
Oracleplsql
OracleplsqlOracleplsql
Oracleplsql
 
Versão 1.56
Versão 1.56Versão 1.56
Versão 1.56
 
Guia Passo a Passo_ Como Criar uma Conta de Serviç... - ServiceNow Community.pdf
Guia Passo a Passo_ Como Criar uma Conta de Serviç... - ServiceNow Community.pdfGuia Passo a Passo_ Como Criar uma Conta de Serviç... - ServiceNow Community.pdf
Guia Passo a Passo_ Como Criar uma Conta de Serviç... - ServiceNow Community.pdf
 
Ns tutorial so
Ns tutorial soNs tutorial so
Ns tutorial so
 
[SAP BW] Process Chain with Invalid Character
[SAP BW] Process Chain with Invalid Character[SAP BW] Process Chain with Invalid Character
[SAP BW] Process Chain with Invalid Character
 

Mais de Cristiano Rafael Steffens

CONVOLUTIONAL NEURAL NETWORKS: The workhorse of image and video
CONVOLUTIONAL NEURAL NETWORKS: The workhorse of image and videoCONVOLUTIONAL NEURAL NETWORKS: The workhorse of image and video
CONVOLUTIONAL NEURAL NETWORKS: The workhorse of image and videoCristiano Rafael Steffens
 
A pipelined approach to deal with image distortion in computer vision - BRACI...
A pipelined approach to deal with image distortion in computer vision - BRACI...A pipelined approach to deal with image distortion in computer vision - BRACI...
A pipelined approach to deal with image distortion in computer vision - BRACI...Cristiano Rafael Steffens
 
A CNN BASED MODEL TO RESTORE ILL EXPOSED IMAGES
A CNN BASED MODEL TO RESTORE ILL EXPOSED IMAGESA CNN BASED MODEL TO RESTORE ILL EXPOSED IMAGES
A CNN BASED MODEL TO RESTORE ILL EXPOSED IMAGESCristiano Rafael Steffens
 
Can Exposure, Noise and Compression affect Image Recognition? An Assessment o...
Can Exposure, Noise and Compression affect Image Recognition? An Assessment o...Can Exposure, Noise and Compression affect Image Recognition? An Assessment o...
Can Exposure, Noise and Compression affect Image Recognition? An Assessment o...Cristiano Rafael Steffens
 
UMA ABORDAGEM COMPARATIVA ENTRE MICROCONTROLADORES: ARDUINO MEGA X ARDUINO DU...
UMA ABORDAGEM COMPARATIVA ENTRE MICROCONTROLADORES: ARDUINO MEGA X ARDUINO DU...UMA ABORDAGEM COMPARATIVA ENTRE MICROCONTROLADORES: ARDUINO MEGA X ARDUINO DU...
UMA ABORDAGEM COMPARATIVA ENTRE MICROCONTROLADORES: ARDUINO MEGA X ARDUINO DU...Cristiano Rafael Steffens
 
FPGA-based sensor integration and communication protocols for automated
FPGA-based sensor integration and communication protocols for automatedFPGA-based sensor integration and communication protocols for automated
FPGA-based sensor integration and communication protocols for automatedCristiano Rafael Steffens
 
Lars 2016 A Texture Driven Approach for Visible Spectrum Fire Detection
Lars 2016 A Texture Driven Approach for Visible Spectrum Fire DetectionLars 2016 A Texture Driven Approach for Visible Spectrum Fire Detection
Lars 2016 A Texture Driven Approach for Visible Spectrum Fire DetectionCristiano Rafael Steffens
 
ICRA 2016 - Interactive section Presentation
ICRA 2016 - Interactive section PresentationICRA 2016 - Interactive section Presentation
ICRA 2016 - Interactive section PresentationCristiano Rafael Steffens
 
Vision-Based System for Welding Groove Measurements for Robotic Welding Appli...
Vision-Based System for Welding Groove Measurements for Robotic Welding Appli...Vision-Based System for Welding Groove Measurements for Robotic Welding Appli...
Vision-Based System for Welding Groove Measurements for Robotic Welding Appli...Cristiano Rafael Steffens
 
Simpósio Unicruz: OpenCV + Python (parte 1)
Simpósio Unicruz: OpenCV + Python (parte 1)Simpósio Unicruz: OpenCV + Python (parte 1)
Simpósio Unicruz: OpenCV + Python (parte 1)Cristiano Rafael Steffens
 
Welding Groove Mapping: Image Acquisition and Processing on Shiny Surfaces - ...
Welding Groove Mapping: Image Acquisition and Processing on Shiny Surfaces - ...Welding Groove Mapping: Image Acquisition and Processing on Shiny Surfaces - ...
Welding Groove Mapping: Image Acquisition and Processing on Shiny Surfaces - ...Cristiano Rafael Steffens
 
Automated control module based on VBM for shipyard welding applications: Stud...
Automated control module based on VBM for shipyard welding applications: Stud...Automated control module based on VBM for shipyard welding applications: Stud...
Automated control module based on VBM for shipyard welding applications: Stud...Cristiano Rafael Steffens
 
An Unconstrained Dataset for Non-stationary Video Based Fire Detection
An Unconstrained Dataset for Non-stationary Video Based Fire DetectionAn Unconstrained Dataset for Non-stationary Video Based Fire Detection
An Unconstrained Dataset for Non-stationary Video Based Fire DetectionCristiano Rafael Steffens
 
Introdução ao processamento de imagens com OpenCV (cont)
Introdução ao processamento de imagens com OpenCV (cont)Introdução ao processamento de imagens com OpenCV (cont)
Introdução ao processamento de imagens com OpenCV (cont)Cristiano Rafael Steffens
 
Um Sistema De Detecção De Fogo Baseado Em Vídeo
Um Sistema De Detecção De Fogo Baseado Em VídeoUm Sistema De Detecção De Fogo Baseado Em Vídeo
Um Sistema De Detecção De Fogo Baseado Em VídeoCristiano Rafael Steffens
 
Um sistema de detecção de chamas utilizando RF e SVM (Short Version)
Um sistema de detecção de chamas utilizando RF e SVM (Short Version)Um sistema de detecção de chamas utilizando RF e SVM (Short Version)
Um sistema de detecção de chamas utilizando RF e SVM (Short Version)Cristiano Rafael Steffens
 

Mais de Cristiano Rafael Steffens (20)

CONVOLUTIONAL NEURAL NETWORKS: The workhorse of image and video
CONVOLUTIONAL NEURAL NETWORKS: The workhorse of image and videoCONVOLUTIONAL NEURAL NETWORKS: The workhorse of image and video
CONVOLUTIONAL NEURAL NETWORKS: The workhorse of image and video
 
A pipelined approach to deal with image distortion in computer vision - BRACI...
A pipelined approach to deal with image distortion in computer vision - BRACI...A pipelined approach to deal with image distortion in computer vision - BRACI...
A pipelined approach to deal with image distortion in computer vision - BRACI...
 
A CNN BASED MODEL TO RESTORE ILL EXPOSED IMAGES
A CNN BASED MODEL TO RESTORE ILL EXPOSED IMAGESA CNN BASED MODEL TO RESTORE ILL EXPOSED IMAGES
A CNN BASED MODEL TO RESTORE ILL EXPOSED IMAGES
 
Can Exposure, Noise and Compression affect Image Recognition? An Assessment o...
Can Exposure, Noise and Compression affect Image Recognition? An Assessment o...Can Exposure, Noise and Compression affect Image Recognition? An Assessment o...
Can Exposure, Noise and Compression affect Image Recognition? An Assessment o...
 
UMA ABORDAGEM COMPARATIVA ENTRE MICROCONTROLADORES: ARDUINO MEGA X ARDUINO DU...
UMA ABORDAGEM COMPARATIVA ENTRE MICROCONTROLADORES: ARDUINO MEGA X ARDUINO DU...UMA ABORDAGEM COMPARATIVA ENTRE MICROCONTROLADORES: ARDUINO MEGA X ARDUINO DU...
UMA ABORDAGEM COMPARATIVA ENTRE MICROCONTROLADORES: ARDUINO MEGA X ARDUINO DU...
 
FPGA-based sensor integration and communication protocols for automated
FPGA-based sensor integration and communication protocols for automatedFPGA-based sensor integration and communication protocols for automated
FPGA-based sensor integration and communication protocols for automated
 
Lars 2016 A Texture Driven Approach for Visible Spectrum Fire Detection
Lars 2016 A Texture Driven Approach for Visible Spectrum Fire DetectionLars 2016 A Texture Driven Approach for Visible Spectrum Fire Detection
Lars 2016 A Texture Driven Approach for Visible Spectrum Fire Detection
 
Php Math and arrays
Php Math and arraysPhp Math and arrays
Php Math and arrays
 
ICRA 2016 - Interactive section Presentation
ICRA 2016 - Interactive section PresentationICRA 2016 - Interactive section Presentation
ICRA 2016 - Interactive section Presentation
 
Vision-Based System for Welding Groove Measurements for Robotic Welding Appli...
Vision-Based System for Welding Groove Measurements for Robotic Welding Appli...Vision-Based System for Welding Groove Measurements for Robotic Welding Appli...
Vision-Based System for Welding Groove Measurements for Robotic Welding Appli...
 
Simpósio Unicruz: OpenCV + Python (parte 1)
Simpósio Unicruz: OpenCV + Python (parte 1)Simpósio Unicruz: OpenCV + Python (parte 1)
Simpósio Unicruz: OpenCV + Python (parte 1)
 
Welding Groove Mapping: Image Acquisition and Processing on Shiny Surfaces - ...
Welding Groove Mapping: Image Acquisition and Processing on Shiny Surfaces - ...Welding Groove Mapping: Image Acquisition and Processing on Shiny Surfaces - ...
Welding Groove Mapping: Image Acquisition and Processing on Shiny Surfaces - ...
 
Automated control module based on VBM for shipyard welding applications: Stud...
Automated control module based on VBM for shipyard welding applications: Stud...Automated control module based on VBM for shipyard welding applications: Stud...
Automated control module based on VBM for shipyard welding applications: Stud...
 
An Unconstrained Dataset for Non-stationary Video Based Fire Detection
An Unconstrained Dataset for Non-stationary Video Based Fire DetectionAn Unconstrained Dataset for Non-stationary Video Based Fire Detection
An Unconstrained Dataset for Non-stationary Video Based Fire Detection
 
Introdução ao processamento de imagens com OpenCV (cont)
Introdução ao processamento de imagens com OpenCV (cont)Introdução ao processamento de imagens com OpenCV (cont)
Introdução ao processamento de imagens com OpenCV (cont)
 
Introdução OpenCV (Pt-Br) com exemplos
Introdução OpenCV (Pt-Br) com exemplosIntrodução OpenCV (Pt-Br) com exemplos
Introdução OpenCV (Pt-Br) com exemplos
 
Um Sistema De Detecção De Fogo Baseado Em Vídeo
Um Sistema De Detecção De Fogo Baseado Em VídeoUm Sistema De Detecção De Fogo Baseado Em Vídeo
Um Sistema De Detecção De Fogo Baseado Em Vídeo
 
Um sistema de detecção de chamas utilizando RF e SVM (Short Version)
Um sistema de detecção de chamas utilizando RF e SVM (Short Version)Um sistema de detecção de chamas utilizando RF e SVM (Short Version)
Um sistema de detecção de chamas utilizando RF e SVM (Short Version)
 
20 pratico cursogxxbr
20 pratico cursogxxbr20 pratico cursogxxbr
20 pratico cursogxxbr
 
17 kb versoes-curso-gxxbr
17 kb versoes-curso-gxxbr17 kb versoes-curso-gxxbr
17 kb versoes-curso-gxxbr
 

Atualização de dados em GeneXus

  • 1. 267
  • 2. 268 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.
  • 3. 269
  • 4. 270
  • 5. 271
  • 6. 272 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.
  • 7. 273
  • 8. 274 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.
  • 9. 275 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.
  • 10. 276
  • 11. 277 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).
  • 12. 278 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.
  • 13. 279 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.
  • 14. 280 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).
  • 15. 281 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 commitautomático.
  • 16. 282
  • 17. 283 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] { regla1; regla2; ... 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].
  • 18. 284
  • 19. 285 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.
  • 20. 286 Vamos supor que temos o seguinte diagrama de Bachman genérico: E no Source de um procedimento fazemos: For each C = &C E = &E D = &D Endfor 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.
  • 21. 287 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.
  • 22. 288 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 each where InvoiceDate <=&date For each defined by InvoiceDetailQuantity DELETE // se eliminam as linhas Endfor DELETE //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).
  • 23. 289 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.
  • 24. 290 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.
  • 25. 291 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.
  • 26. 292 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 each where InvoiceDate >= &startDate where InvoiceDate <= &endDate where 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.