11 data providers-cursogxxbr

613 visualizações

Publicada em

Genexus Course

Publicada em: Tecnologia
0 comentários
1 gostou
Estatísticas
Notas
  • Seja o primeiro a comentar

Sem downloads
Visualizações
Visualizações totais
613
No SlideShare
0
A partir de incorporações
0
Número de incorporações
1
Ações
Compartilhamentos
0
Downloads
13
Comentários
0
Gostaram
1
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

11 data providers-cursogxxbr

  1. 1. 242
  2. 2. 243 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).
  3. 3. 244 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... ).
  4. 4. 245 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.
  5. 5. 246 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...
  6. 6. 247 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.
  7. 7. 248 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)...
  8. 8. 249 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.
  9. 9. 250 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.
  10. 10. 251 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.
  11. 11. 252 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.
  12. 12. 253 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 = &today CustomerName = CustomerName BillInvoicePeriodStartDate = &start BillInvoicePeriodEndDate = &end BillAmount = sum (InvoiceAmount, ... ) &quantity = &quantity + 1 } BillQuantity = &quantity } Com o mesmo resultado. GeneXus tem inteligência suficiente para matchear com o SDT.
  13. 13. 254
  14. 14. 255 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.
  15. 15. 256 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.
  16. 16. 257
  17. 17. 258
  18. 18. 259
  19. 19. 260 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
  20. 20. 261
  21. 21. 262
  22. 22. 263
  23. 23. 264 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 quais CUSTOMER.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”.
  24. 24. 265
  25. 25. 266

×