Professional Documents
Culture Documents
Aplicaciones Basadas
en Tecnologas
Genexus
Introduccin Terica
Herramientas y Metodologas
Modelado de la realidad
MODELO DE LA
REALIDAD
Satisface
Ingeniera Inversa
BASE
DE
DATOS
PROGRAMAS
VISIONES
DE
USUARIOS
REALIDAD
DESCRIPCIN
DE OBJETOS
Utilizando GeneXus, la tarea bsica del analista es la descripcin de la realidad. Slo el ser humano
puede desarrollar esta tarea ya que slo l puede entender el problema del usuario.
El analista GeneXus trabaja en alto nivel, en vez de realizar tareas de bajo nivel como: disear
archivos, normalizar, disear programas, programar, buscar y eliminar los errores de los programas.
Para comenzar el desarrollo de una aplicacin con GeneXus, el primer paso consiste en crear un
nuevo proyecto o base de conocimiento.
Una vez creada una nueva base de conocimiento (en ingls: knowledge base; abreviado: KB), el
siguiente paso es describir las visiones de los usuarios. Para ello se deben identificar los objetos de la
realidad (prestando atencin a los sustantivos que los usuarios mencionan en sus descripciones,
como por ejemplo: clientes, productos, facturas) y pasar a definirlos mediante objetos GeneXus.
Con la definicin de estos objetos, GeneXus puede extraer el conocimiento y disear la base de
datos y los programas de la aplicacin en forma automtica.
REALIDAD
DESCRIPCIN
DE OBJETOS
BASE DE
CONOCIMIENTO
Utilizando GeneXus, la tarea bsica del analista es la descripcin de la realidad. Slo el ser humano
puede desarrollar esta tarea ya que slo l puede entender el problema del usuario.
El analista GeneXus trabaja en alto nivel, en vez de realizar tareas de bajo nivel como: disear
archivos, normalizar, disear programas, programar, buscar y eliminar los errores de los programas.
Para comenzar el desarrollo de una aplicacin con GeneXus, el primer paso consiste en crear un
nuevo proyecto o base de conocimiento.
Una vez creada una nueva base de conocimiento (en ingls: knowledge base; abreviado: KB), el
siguiente paso es describir las visiones de los usuarios. Para ello se deben identificar los objetos de la
realidad (prestando atencin a los sustantivos que los usuarios mencionan en sus descripciones,
como por ejemplo: clientes, productos, facturas) y pasar a definirlos mediante objetos GeneXus.
Con la definicin de estos objetos, GeneXus puede extraer el conocimiento y disear la base de
datos y los programas de la aplicacin en forma automtica.
BASE
DE
DATOS
DESCRIPCIN
DE OBJETOS
BASE DE
CONOCIMIENTO
PROGRAMAS
Transacciones
(Trns)
Procedimientos
(Procs)
Data Providers
Web Panels
(DP)
(Wbps)
Una vez creada una base de conocimiento, el siguiente paso consiste en comenzar a describir
los objetos de la realidad mediante objetos GeneXus.
Los objetos GeneXus ms importantes son:
Transacciones
Permiten definir los objetos de la realidad que el usuario manipula (ej: clientes, productos,
proveedores, facturas, etc.). Son los primeros objetos en definirse, ya que a travs de las
transacciones, GeneXus infiere el diseo de la base de datos.
Adems de tener por objetivo la definicin de la realidad y la consecuente creacin de la base de
datos normalizada, cada transaccin tiene asociada una pantalla para ambiente windows y otra
para ambiente Web, para permitir al usuario dar altas, bajas y modificaciones en forma
interactiva a la base de datos. El analista GeneXus decidir si trabajar en ambiente windows,
Web, o ambos, y GeneXus generar los programas para ello.
Procedimientos
Permiten recuperar informacin de la base de datos, y desplegarla ya sea en la pantalla, en un
archivo o impresa en papel. Son los tpicos listados o informes. Adems, permiten la
actualizacin de la informacin de la base de datos.
Data Providers
Permiten cargar y devolver datos jerrquicos para intercambio de informacin entre objetos de la
misma aplicacin o de otras aplicaciones.
Web Panels
Permiten al usuario realizar interactivamente consultas a la base de datos, a travs de una
pantalla. Ejemplo: un web panel permite al usuario ingresar un rango de caracteres, y muestra a
continuacin todos los clientes cuyos nombres se encuentran dentro del rango.
Son objetos web muy flexibles que se prestan para mltiples usos. No permiten la actualizacin
de la base de datos, sino solo su consulta.
Procedimientos
(Procs)
Data Providers
(DP)
Web Panels
(Wbps)
Base
Basede
deConocimiento
Conocimiento
Base
de
Datos
Los primeros objetos que se definen son las transacciones, ya que es a partir de ellas que
GeneXus extrae el conocimiento necesario para disear el modelo de datos normalizado (en 3era.
forma normal). Luego se van definiendo los dems objetos que correspondan.
Procedimientos
(Procs)
Data Providers
(DP)
Web Panels
(Wbps)
Base
Basede
deConocimiento
Conocimiento
Base
de
Datos
Programas
Creacin
BD
GeneXus genera automticamente los programas necesarios para crear la base de datos y los
ejecuta. De esta manera obtenemos la base de datos creada por GeneXus en forma
automtica.
Generacin de los
Programas de la aplicacin
Transacciones
(Trns)
Procedimientos
(Procs)
Data Providers
(DP)
Web Panels
(Wbps)
Base
Basede
deConocimiento
Conocimiento
Base
de
Datos
Programas de Aplicacin
(Trns, Procs, Wbps, DPs, etc.)
Luego, GeneXus genera programas de aplicacin para interactuar con la base de datos
previamente creada.
10
Procedimientos
(Procs)
Data Providers
(DP)
Web Panels
(Wbps)
Base
Basede
deConocimiento
Conocimiento
Base
de
Datos
Programas de Aplicacin
(Trns, Procs, Wbps, DPs, etc.)
Una vez creada la base de datos y generados los programas, contamos con una aplicacin pronta
para ejecutar.
11
Nuevos
Procedimientos
Nuevos
Data Providers
Nuevos
Web Panels
Base
Basede
deConocimiento
Conocimiento
Base
de
Datos
Nueva
Nueva
Base
Base
de
de
Datos
Datos
Programas de Aplicacin
(Trns, Procs, Wbps, DPs, etc.)
12
Nuevos
Procedimientos
Anlisis
de
impacto
Base
de
Datos
Nuevos
Data Providers
Nuevos
Web Panels
Base
Basede
deConocimiento
Conocimiento
Nueva
Nueva
Base
Base
de
de
Datos
Datos
Programas de Aplicacin
(Trns, Procs, Wbps, DPs, etc.)
Algunas veces la nueva base de datos coincide con la anterior. Otras veces esto no ocurre, y la base
de datos debe sufrir alguna modificacin para representar la nueva realidad.
El analista debe estudiar el reporte de anlisis de impacto y resolver si desea realizar
efectivamente los cambios en la base de datos, o renunciar a ello dejando la base de datos como
estaba.
13
Generacin de Programas de
Reorganizacin de la Base de Datos
Nuevas
Transacciones
Nuevos
Procedimientos
Programas
de
Reorganiz.
Base
de
Datos
Nuevos
Data Providers
Nuevos
Web Panels
Base
Basede
deConocimiento
Conocimiento
Nueva
Nueva
Base
Base
de
de
Datos
Datos
Programas de Aplicacin
(Trns, Procs, Wbps, DPs, etc.)
Si el analista opta por aplicar los cambios propuestos, decimos que opt por reorganizar la base de
datos. Utilizamos este trmino para referirnos a la accin de aplicar cambios fsicos sobre la base de
datos.
GeneXus generar los programas que implementan las modificaciones sobre las estructuras
fsicas de la base de datos, y mediante su ejecucin nos brindar la nueva versin de la base de
datos con los cambios efectuados.
14
Nuevos
Procedimientos
Nuevos
Data Providers
Base
Basede
deConocimiento
Conocimiento
Nueva
Base
de
Datos
Nuevos
Web Panels
Anlisis
de Impacto
sobre los
programas
Nuevos Programas de
Aplicacin
(Trns, Procs, Wbps, DPs, etc.)
Ya sea que se requiera reorganizar la base de datos o no, considerando las nuevas definiciones
introducidas, GeneXus estudiar el impacto de los cambios sobre los programas actuales.
15
Nuevos
Procedimientos
Nuevos
Data Providers
Base
Basede
deConocimiento
Conocimiento
Nueva
Base
de
Datos
Nuevos
Web Panels
Generacin
de
programas
Nuevos Programas de
Aplicacin
(Trns, Procs, Wbps, DPs, etc.)
16
Nuevos
Procedimientos
Nuevos
Data Providers
Nuevos
Web Panels
Base
Basede
deConocimiento
Conocimiento
Nueva
Base
de
Datos
De modo que nuevamente contaremos con una aplicacin pronta para ejecutar, con los cambios
aplicados.
17
Environments
Ellugardondesealmacenalainformacinparagenerarla
aplicacinenciertaplataformadeejecucinsellamaEnvironment.
Environments:
Implementation #1
C# & SQL Server
C#
Application
SQL
Implementation #2
GeneXus
Project
C# & MySQL
C#
Application
MySQL
Implementation #3
Java Application
MySQL
Knowledge Base
ElusodevariosEnvironments permitedistintasimplementaciones
delamismaaplicacin.
18
Environments
Cuandosecreaunabasedeconocimiento(KB),GeneXuspideal
usuarioqueseleccioneelEnvironment conelquevaatrabajar:
Conestosdatos,secreaautomticamenteunEnvironment.
Para crear una base de conocimiento, se debe seleccionar en la barra de men de GeneXus, el tem File /
New Knowledge Base. A continuacin aparecer un dilogo como el siguiente:
Se deber indicar;
Nombre de la Knowledge Base: en nuestro caso ser BillingSystem.
Directorio donde se crear.
El Environment por defecto: vea como se muestran lenguajes de programacin. GeneXus los utilizar para
crear los programas asociados a la base de datos. Las opciones ofrecidas son: C# Environment, Java
Environment y Ruby Environment.
Language: Idioma en el que aparecern los botones, mensajes, etc.
Al momento de crear la KB se comienza a definir el ambiente de implementacin (Environment) cuyas
definiciones sern luego completadas al momento de ejecutar la aplicacin (nombre de la base de datos,
servidor, forma de conexin, etc).
19
Environments
ParaverelEnvironment creado,seleccionamoslaventanade
Preferences delKnowledge BaseNavigator:
Default
Environment
20
Environments
Paratenerimplementacionesendistintasplataformas,creamos
variosEnvironments.
21
Environments
VemoslosEnvironments creados:
Environments:
GeneXus
Project
Java & MySQL
Knowledge Base
22
Metodologa Incremental
Construir una aplicacin mediante aproximaciones sucesivas.
DEFINICION
INICIAL
23
Metodologa Incremental
Paraaplicarundesarrolloincremental,puedomanejardistintas
versiones delaaplicacin.
Sobre el versionado (de qu se trata, cmo realizarlo, etc.) volveremos al final. Por ahora alcanza con
saber que al crear la base de conocimiento, los programas que estaremos ejecutando, programas
reales, sern una versin de la aplicacin, de prueba. Una vez que decidamos que esa versin est
lista para ser puesta en produccin, alcanzar con hacer otra versin de la aplicacin, y listo!.
24
Ventajas de la Prototipacin
Permiteverresultadosenformatemprana.
Permiteelseguimientodelosrequerimientosdelusuario.
Deteccindeerroresenformatemprana.
Lograelcompromisodelosusuariosconeldesarrollo.
Sistemasdemejorcalidad.
Como la implementacin de sistemas es habitualmente una tarea que insume bastante tiempo, y muchos de
estos problemas slo son detectados en las pruebas finales del sistema, el costo en tiempo y dinero de
solucionarlos se torna muy grande. Sabido es que la realidad no permanece esttica, por lo que no es
razonable suponer que se pueden mantener congeladas las especificaciones mientras se implementa el
sistema. Sin embargo, debido al tiempo que suele insumir la implementacin, muchas veces esto se hace y
se acaba implementando una solucin relativamente insatisfactoria.
El impacto de estos problemas disminuira mucho si se consiguiera probar cada especificacin
inmediatamente y saber cul es la repercusin de cada cambio sobre el resto del sistema. Una primera
aproximacin a esto, ofrecida por diversos sistemas, es la posibilidad de mostrar al usuario formatos de
pantallas, informes, etc., animados por mens. Esto permite ayudar al usuario a tener una idea de qu
sistema se le construir, pero al final siempre se presentan sorpresas.
Una situacin bastante diferente sera la de poner a disposicin del usuario para su ejecucin, una
aplicacin funcionalmente equivalente a la deseada hasta en los mnimos detalles. Y esto es lo que ofrece
GeneXus! Un prototipo GeneXus es una aplicacin pronta funcionalmente equivalente a la aplicacin de
produccin.
As es que la aplicacin puede ser totalmente probada antes de ponerse en produccin; y durante las
pruebas, el usuario final puede probar de una forma natural no solamente formatos de pantallas, informes,
etc., sino tambin frmulas, reglas del negocio, estructuras de datos, etc., y trabajar con datos reales.
Esto solo es posible gracias a la construccin automtica que realiza GeneXus del soporte computacional
(base de datos y programas).
25
Objeto Transaccin
26
Transacciones
Generalidades
Definicin
Objeto a partir del cual GeneXus crear en forma
automtica la base de datos en 3era forma normal
Describen las visiones de los usuarios.
Contienen toda la informacin necesaria acerca de los datos de
la aplicacin y de cmo los usuarios accedern al sistema para su
manejo (insertar, modificar y eliminar).
Elementos que las componen:
27
Transacciones
Estructura
Ejemplo: Se necesita registrar informacin de proveedores.
Identificador de proveedor
Nombre de proveedor
Direccin de proveedor
Telfono de proveedor
-------------------------------------------------------------------------------------------------------------1 El asterisco corresponde a una notacin terica que utilizamos para indicar que el atributo es
identificador. Como veremos, nuestro asterisco en GeneXus aparece representado por un cono de llave y
el usuario podr configurarlo mediante un men contextual que le ofrecer esta posibilidad.
28
Transacciones
Estructura
Vista de la estructura en GeneXus:
Atributos Clave
En la pgina anterior hemos explicado que el asterisco a continuacin del atributo SupplierId indica que se trata
del identificador de la transaccin. Toda transaccin debe tener un identificador, esto es, un atributo o conjunto de
atributos que definan la unicidad.
En el ejemplo no podrn existir dos proveedores con el mismo valor de SupplierId. En definitiva se trata del
concepto de clave primaria, en tanto, para hacer la eleccin de los atributos que la componen, se deben tener en
cuenta los requisitos del objeto de la realidad.
En los casos en los cuales no se pueda determinar un identificador, se debe optar por crear un atributo artificial
(no existente en la realidad), y que su valor se asigne internamente, por ejemplo, en forma correlativa.
Como se puede observar en el editor de transacciones de GeneXus, un cono de llave representa el asterisco que
nosotros utilizamos como notacin terica.
Atributo descriptor
El cono con una lupa representa al atributo que mejor describe o representa a la transaccin. En otras palabras
sera el atributo que tiene mayor carga semntica en la transaccin.
Por defecto el primer atributo en la estructura de la transaccin que sea de tipo de datos character, se definir
como atributo descriptor. Es posible definir a otro atributo como descriptor utilizando el men popup
correspondiente, as como no definir ninguno.
29
Transacciones
Estructura
Ejemplo: Se necesita registrar informacin referente a facturas de venta.
Invoice
{
InvoiceId*
InvoiceDate
CustomerId
CustomerName
Identificador de factura
Fecha de factura
Identificador de cliente
Nombre de cliente
Detail
{
ProductId*
Identificador de producto
ProductDescription
Descripcin de producto
ProductPrice
Precio de producto
InvoiceDetailQuantity
Cantidad de producto llevada en la lnea
InvoiceDetailAmount
Importe de lnea de factura
}
InvoiceAmount
Importe total de la factura
30
Transacciones
Estructura
Vista de la estructura en GeneXus
Invoice {
InvoiceId*
InvoiceDate
CustomerId
CustomerName
InvoiceAmount
Detail
{ProductId*
ProductDescription
ProductPrice
InvoiceDetailQuantity
InvoiceDetailAmount
Payment
{InvoicePaymentDate*
InvoicePaymentAmount}}
}
Con la estructura de la izquierda se define que una factura tiene muchos productos y muchos pagos, pero no
hay una relacin directa entre los productos y los pagos (a no ser el hecho de pertenecer a la misma factura).
En la estructura de la derecha se registran los pagos por producto llevado.
Es sencillo comprender que el segundo y tercer nivel de la transaccin de la izquierda, son paralelos. Ambos
se encuentran anidados al primer nivel, pero entre ellos, son paralelos. En la estructura de la derecha, son
todos niveles anidados.
------------------------------------------------------------------------------------------------------------------1 Como veremos luego, el tipo que se define para un nivel de una transaccin, ser utilizado para trabajar con business
components, concepto relacionado a las transacciones.
31
Transacciones
Definicin del modelo de datos: estructuras de las transacciones
Transaccin
Supplier
{
SupplierId*
SupplierName
SupplierAddress
SupplierPhone
}
Invoice
{
InvoiceId*
InvoiceDate
CustomerId
CustomerName
InvoiceId*
InvoiceDate
CustomerId
CustomerName
InvoiceAmount
Detail
{
ProductId*
ProductDescription
ProductPrice
InvoiceDetailQuantity
InvoiceDetailAmount
}
InvoiceAmount
Tabla
SUPPLIER
SupplierId*
SupplierName
SupplierAddress
SupplierPhone
Tabla
INVOICE
Transaccin
Tabla
INVOICEDETAIL
InvoiceId*
ProductId*
ProductDescription
ProductPrice
InvoiceDetailQuantity
InvoiceDetailAmount
GeneXus utiliza la estructura de las transacciones para capturar el conocimiento necesario para definir
automticamente cul es el modelo de datos que debe crear.
Para poder realizar la normalizacin de la base de datos llevndola a 3era. forma normal, GeneXus debe
extraer las dependencias funcionales existentes entre los atributos definidos en la base de conocimiento.
En la base de conocimiento de nuestro ejemplo, hemos definido a la transaccin Proveedores y de su
estructura GeneXus extrae las siguientes dependencias funcionales:
SupplierId {SupplierName, SupplierAddress, SupplierPhone}
Dadas estas dependencias funcionales, GeneXus determina que debe crear una tabla que tendr por
defecto el mismo nombre que la transaccin (SUPPLIER)1, y que estar conformada ni ms ni menos
que por los cuatro atributos anteriores, siendo SupplierId la clave primaria de la misma:
SUPPLIER
SupplierId
SupplierName
SupplierAddress
SupplierPhone
Diremos que la transaccin Supplier tiene asociada la tabla SUPPLIER en el entendido de que cuando
se ingresen, modifiquen o eliminen datos por medio de la transaccin, stos se estarn almacenando,
modificando o eliminando fsicamente en la tabla asociada.
-----------------------------------------------------------------------------------------------------------1 En la documentacin, para distinguir el nombre de una tabla del nombre de una transaccin escribiremos el nombre
de la tabla todo en mayscula.
32
A partir de la estructura de la transaccin Invoice, GeneXus determina que debe crear dos tablas:
Tabla INVOICE, correspondiente al primer nivel de la transaccin:
INVOICE
InvoiceId
CustomerId
CustomerName
InvoiceDate
InvoiceAmount
INVOICEDETAIL
InvoiceId
ProductId
InvoiceDetailQuantity
ProductDescription
ProductPrice
InvoiceDetailAmount
33
Transacciones
Estructura
Al definir las nuevas transacciones:
Customer
{
CustomerId*
CustomerName
CustomerAddress
CustomerGender
}
Product
{
ProductId*
ProductDescription
ProductPrice
ProductStock
}
Luego de haber modelado la transaccin Invoice, nos damos cuenta que hay informacin de clientes y de
productos que nos interesa mantener independientemente de las facturas. Es decir, los clientes y los
productos son dos objetos de la realidad independientes de las facturas, por lo tanto creamos las dos nuevas
transacciones Customer y Product detalladas arriba.
Dependencias funcionales
Con estas nuevas transacciones definidas, aparecen nuevas dependencias funcionales:
CustomerId {CustomerName, CustomerAddress, CustomerGender, CustomerStatus}
ProductId {ProductDescription, ProductPrice, ProductStock}
que conducen directamente a la creacin de dos nuevas tablas:
CUSTOMER
CustomerId
CustomerName
CustomerAddress
CustomerGender
ProductId
ProductDescription
ProductPrice
ProductStock
34
Transacciones
Normalizacin: cambios en las tablas
Tabla
INVOICE
InvoiceId*
InvoiceDate
CustomerId
CustomerName
InvoiceAmount
Tabla
INVOICEDETAIL
InvoiceId*
ProductId*
ProductDescription
ProductPrice
InvoiceDetailQuantity
InvoiceDetailAmount
Tabla CUSTOMER
CustomerId*
CustomerName
CustomerAddress
CustomerGender
Tabla PRODUCT
Tabla
SUPPLIER
SupplierId*
SupplierName
SupplierAddress
SupplierPhone
ProductId*
ProductDescription
ProductPrice
ProductStock
El conjunto total de dependencias funcionales existentes requiere que deban realizarse algunas
modificaciones en las tablas INVOICE e INVOICEDETAIL diseadas previamente para que el diseo de la
base de datos permanezca en 3era. forma normal1.
Si representamos sobre las tablas CUSTOMER e INVOICE las dependencias funcionales encontradas para
sus atributos:
podemos ver claramente que INVOICE viola la 3era. forma normal (existe una dependencia funcional
transitiva):
InvoiceId CustomerId
CustomerId CustomerName
InvoiceId CustomerName
por lo tanto GeneXus normaliza, quitando el atributo CustomerName de la tabla INVOICE:
35
Ahora veamos las dependencias funcionales encontradas en las tablas PRODUCT e INVOICEDETAIL:
podemos percibir claramente que la tabla INVOICEDETAIL est violando la 3era. forma normal (existen atributos que
estn dependiendo en forma parcial de la clave primaria):
ProductId ProductDescription
ProductId ProductPrice
Por lo tanto GeneXus normaliza, quitando los atributos ProductDescription y ProductPrice de la tabla INOVICEDETAIL:
36
Transacciones
Relaciones: establecidas por los nombres de atributos
Conceptos iguales deben tener igual nombre
Invoice
{
InvoiceId*
CustomerId
CustomerName
...
}
Customer
{
CustomerId*
CustomerName
}
Invoice
{
InvoiceId*
InvoiceCustomerId
...
}
Customer
{
CustomerId*
CustomerName
}
incorrecto
VendorInvoice
{
VendorInvoiceId*
Date
SupplierId*
SupplierName
...
}
Conceptos iguales deben tener el mismo nombre y conceptos diferentes deben ser nombrados
diferentes.
GeneXus establece las relaciones a travs de los nombres de los atributos, de modo que cuando
encuentra atributos de igual nombre en distintas transacciones, entiende que se trata del mismo
concepto, y mediante dicho conocimiento es que puede normalizar.
En el ejemplo que venimos viendo, cuando GeneXus encuentra el atributo de nombre CustomerId tanto
en la transaccin Customer como en la transaccin Invoice, analiza que: el atributo se llama igual en
ambas transacciones, as que se refiere al mismo concepto. En la transaccin Customer, CustomerId
est marcado como identificador, lo que significa que ser clave primaria en la tabla fsica
CUSTOMER; entonces en la tabla fsica INVOICE ser clave fornea.
El atributo CustomerName, por su parte, tambin se encuentra tanto en la transaccin Customer
como en la transaccin Invoice, pero a diferencia de CustomerId, no est marcado como identificador
en ninguna transaccin del modelo; por tanto GeneXus entiende que se trata de un atributo
secundario. Las dependencias funcionales indican que a CustomerName lo determina CustomerId:
InvoiceId CustomerId
CustomerId CustomerName
as que GeneXus incluir CustomerName en la tabla fsica CUSTOMER (y no en la tabla fsica
INVOICE).
Atributos primarios y secundarios
Un atributo se califica como primario cuando el mismo es identificador en alguna transaccin del
modelo. En el ejemplo que venimos viendo, CustomerId es un atributo primario ya que es identificador
en la transaccin Customer.
CustomerName, en cambio, es un atributo secundario ya que no es identificador en ninguna
transaccin del modelo.
37
Invoice
{
InvoiceId*
InvoiceDate
CustomerId
CustomerName
Detail
{
ProductId*
ProductDescription
ProductPrice
InvoiceDetailQuantity
InvoiceDetailAmount
}
InvoiceAmount
}
Customer
{
CustomerId*
CustomerName
CustomerAddress
CustomerGender
}
Product
{
ProductId*
ProductDescription
ProductPrice
ProductStock
}
Probablemente usted no comprenda la razn por la cual los atributos secundarios CustomerName,
ProductDescription y ProductPrice se han dejado en la estructura de la transaccin Invoice.
La explicacin es la siguiente: las estructuras de las transacciones no son equivalentes a
estructuras de tablas fsicas. En las estructuras de las transacciones se pueden incluir ciertos
atributos que no estarn en la o las tablas fsicas asociadas, ya que a la hora de reorganizar la base de
datos GeneXus analizar el conjunto total de dependencias funcionales existentes en la base de
conocimiento, y crear -o modificar, segn el caso- las tablas fsicas, dejndolas en 3 forma normal.
Ahora, con qu finalidad hemos dejado los atributos secundarios CustomerName, ProductDescription
y ProductPrice en la estructura de la transaccin Invoice? Los hemos dejado para poder incluirlos en
alguno de los forms (GUI-Windows y/o Web) asociados a la transaccin Invoice y as poder visualizar
los valores de dichos atributos en tiempo de ejecucin.
Dichos atributos, como hemos explicado, no quedarn almacenados ni en la tabla INVOICE, ni en la
tabla INVOICEDETAIL; sin embargo, en tiempo de ejecucin cuando el usuario ingrese a travs de
alguno de los forms (GUI-Windows y/o Web) un valor de CustomerId (atributo que s se almacenar en
la tabla INVOICE siendo clave fornea), a continuacin se mostrar el CustomerName
correspondiente. Decimos que el atributo CustomerName es un atributo inferido en la transaccin
Invoice, ya que su valor no se encuentra almacenado en ninguna de las tablas asociadas a la
transaccin, sino que se infiere es decir, se obtiene- de la tabla CUSTOMER, dado el valor del
atributo CustomerId.
Anlogamente, los atributos ProductDescription y ProductPrice tambin son inferidos en la transaccin
Invoice, ya que no se encuentran almacenados en las tablas asociadas a la misma, sino que sus
valores se infieren de la tabla PRODUCT, para ser mostrados en pantalla.
38
Transacciones
Estructura: nombrado de atributos
Es conveniente usar padrones para los nombres de los
atributos.
Facilitan la tarea de nombrado.
Facilitan la tarea de integracin de bases de conocimiento.
Facilitan la lectura del cdigo generado.
39
Transacciones
Estructura: nombrado de atributos
Nomenclatura GIK
Componente de Entidad + Categor
Categora [+ Calificador + Complemento]
Entity Component
Category
Cliente
Id
Qualifier
Cliente
Nombre
Cliente
Fecha
Inicial
Customer
Cliente
Fecha
Final
Customer
Factura
Id
Factura
Fecha
FacturaDetalle
Cantidad
Invoice
FacturaCompra
Id
Invoice
y en ingls:
Entity Component
Vencimiento
Qualifier
Category
Id
Name
Customer
Start
Date
Customer
End
Date
Id
Due
Date
InvoiceDetail
Amount
VendorInvoice
id
40
41
Demo
Una vez creada la base de conocimiento: creacin
de las primeras transacciones.
Una vez creada la base de conocimiento (ver introduccin terica), la misma quedar abierta para que se
empiecen a crear las transacciones.
La creacin de objetos, se realiza presionando Ctrl+N. Los objetos creados quedarn en la carpeta Objects que
se puede ver en la Folder View de la ventana KB Navigator.
Si se desea que el objeto a crear quede guardado en otra carpeta, se deber posicionar en dicha carpeta y
luego hacer clic con el botn derecho del mouse. En el men elegir New Object.
Tambin se podr indicar la carpeta en el cuadro de creacin de un objeto como se ve en la imagen.
Se desplegar un dilogo en el cual se deber elegir el tipo de objeto que se desea crear (en este caso el tipo
de objeto: Transaction), dar un nombre al objeto que se est creando (por ejemplo: Customer o Invoice),
una descripcin larga, y la carpeta en la cual guardar el objeto.
Una vez creada la transaccin, la misma quedar abierta para que se defina su estructura y dentro de ella sus
atributos.
42
Transacciones
Definicin de atributos
F4
Para definir un atributo, simplemente se debe digitar en el primer campo de una lnea (o rama) de la
estructura, el nombre del atributo que se desea crear. Mediante la tecla de tabulacin se puede pasar a los
siguientes campos para indicar el tipo de datos del atributo, as como su descripcin, si admitir valores
nulos de la base de datos, y en el caso que el mismo vaya a ser una frmula (concepto que veremos en
breve), cmo calcularla. Con la tecla Enter se puede pasar a la siguiente lnea, para definir otro atributo.
Una vez definidos los atributos en la estructura de la transaccin, solamente restar guardar / salvar los
cambios.
Si se necesita modificar el nombre de un atributo, su tipo de datos, descripcin, nulabilidad, o frmula,
bastar con hacer doble clic sobre el campo implicado en la estructura, y el mismo se habilitar y se podr
editar. Luego se debern guardar los cambios, nuevamente.
Para indicar que uno o ms atributos son identificadores en la transaccin, se los debe seleccionar y
presionar CTRL + K; en consecuencia aparecern con un smbolo de llave.
Para definir que comienza otro nivel en la transaccin, se debe digitar CTRL + L, y automticamente se
producir una indentacin y el usuario deber darle nombre a ese nivel, as como definir el nombre de su
tipo de datos1 y una descripcin para el nivel.
Para indicar que un atributo de uno de los niveles de la transaccin ser el atributo descriptor, se lo debe
seleccionar y presionar CTRL+D.
GeneXus cuenta con mens pop up2, que son mens que se abren cuando el usuario est posicionado en
determinado contexto y da clic con el botn derecho del mouse. Por ejemplo, al hacer clic con el botn
derecho del mouse sobre un atributo de la estructura, se abre un men pop up sobre el atributo
seleccionado, que ofrece varias utilidades, como por ejemplo indicar que el atributo es clave (opcin
Toggle key), quitarlo de la estructura, pasarlo a un siguiente nivel de anidacin, etc.
Cada atributo tiene propiedades. Algunas de ellas (las fundamentales y obligatorias) son las que se ofrecen
directamente en la estructura para su ingreso inline. Para acceder al dilogo que permite configurar todas
las propiedades de un atributo, se debe seleccionar el tem Properties del men contextual, o presionar la
tecla F4. En la figura hemos cambiado la propiedad Autonumber que como veremos oportunamente,
permite autonumerar atributos clave primaria.
---------------------------------------------------------------------------------------------------1 Veremos su utilidad cuando estudiemos los business components.
2 Tambin llamados contextuales dado que varan segn el contexto.
43
44
Control Info
A un atributo se le puede asociar un tipo de control. Los tipos de controles posibles son:
- Edit
- Radio Button
- Check Box
- Combo Box
- List Box
- Dynamic Combo Box
- Dynamic List Box
La asociacin de cierto tipo de control a un atributo, sirve para especificar el tipo de control por defecto que se utilizar
para el atributo cada vez que se lo incluya en un form.
Cuando se define un atributo con un tipo de datos bsico, el tipo de control que tiene asociado es Edit, pudiendo el
programador cambiarlo a cualquiera de los otros tipos. En general GeneXus elige el tipo de control para un atributo
dependiendo de su tipo de datos. Si es un dominio enumerado, como veremos, elegir Radio Button o Como Box,
dependiendo de la cantidad de valores del dominio.
En el grupo Control Info del dilogo de edicin de las propiedades de un atributo es donde el programador podr
cambiar el tipo de control asociado al atributo y dependiendo del tipo de control seleccionado, se solicitar distinta
informacin complementaria.
Luego, cada vez que se agregue el atributo en un form se presentar automticamente con el tipo de control que tenga
asociado aqu.
Nota
En caso de asociar al atributo el tipo Edit, se podr especificar que disfrace sus valores, mostrando los de otro atributo
(propiedad InputType), e incluso que sugiera los valores posibles al usuario, a medida que ste vaya digitando
(propiedad Suggest), entre otras, como veremos luego, cuando estudiemos Descripciones en lugar de cdigos.
Tambin se puede elegir el color de la fuente de letra que se desea asociar por defecto al atributo, as como el color de
fondo, de modo que cada vez que se agregue el atributo en un form, se presente automticamente con los colores que
se le hayan asociado (ver grupo Appearance).
45
Transacciones
Atributos: Tipos de Datos
Numeric, Character, Date, Boolean
VarChar
- Equivalente a Character, salvo en la forma en que se almacena
en la BD.
- Propiedades Maximum Length y Avarage Length asociadas.
Long Varchar
- Permite almacenar textos largos, comentarios, etc. (memo).
DateTime
- Permite almacenar una combinacin de fecha y hora.
Blob
- Permite almacenar cualquier tipo de informacin: texto,
imgenes, videos, planillas, etc., en la base de datos.
Numeric: Permite almacenar datos numricos. Cuando se selecciona este tipo de datos se debe indicar
la cantidad total de dgitos del nmero, la cantidad de posiciones decimales, y si permite signo o no.
Ejemplo:
Si definimos que el tipo de datos del atributo InvoiceAmount es numrico de largo 10, con decimales 2, y
sin signo, estamos especificando que representar nmeros con hasta 7 dgitos en la parte entera y 2
decimales (7 dgitos en la parte entera + punto + 2 dgitos para los decimales = 10 dgitos).
Character: Permite almacenar cualquier tipo de texto (caracteres y dgitos). Para este tipo de datos, se
debe indicar el largo.
Ejemplo: El atributo CustomerName que utilizamos para almacenar el nombre de un cliente, es de tipo
Character y si sabemos que nunca un nombre tendr ms de 20 caracteres, podemos fijar el largo: 20.
Date: Permite almacenar una fecha.
Ejemplo: El atributo InvoiceDate que utilizamos para almacenar la fecha de una factura, ser de este tipo
de datos.
El formato a utilizar para las fechas (da-mes-ao, mes-da-ao), se configura en forma genrica para todo
el modelo dentro de un tipo especial de objeto, el objeto Language correspondiente al lenguaje en el que
se generar el modelo. El objeto language existe para poder tener una misma aplicacin traducida en
cualquier lenguaje.
La eleccin de presentar el ao con 2 dgitos o 4, se configura con la propiedad Picture de cada atributo.
Boolean: permite que un atributo o variable asuma los valores lgicos: True, False.
46
VarChar: Permite almacenar texto de largo variable. Su funcin, en contraposicin al Character, es optimizar el
47
Transacciones
Definicin de variables
En todo objeto GeneXus es posible definir variables.
Las variables son nicamente visibles dentro del objeto; es decir, son
locales.
Editor similar al de la estructura de las transacciones:
Para definir variables en determinado objeto, se debe seleccionar el selector Variables, como se muestra en la
figura.
Este selector muestra variables definidas por defecto (Standard variables, como por ejemplo la variable Today
que contiene la fecha del sistema) para el objeto, y permite definir variables nuevas a travs de un editor
similar al de las transacciones.
Tambin se puede ir a la opcin Insert de la menubar y elegir Variables. En el cuadro de dilogo que se
desplegar seleccionar New Variable.
Este dilogo solicita el nombre de la variable, su descripcin, tipo de datos y largo, o dominio, de forma
anloga a cuando se define un atributo.
La propiedad Dimensions permite indicar si la variable ser escalar o si se tratar de un vector (1 dimensin) o
matriz (2 dimensiones). El valor que ofrece por defecto esta propiedad es escalar.
48
Transacciones
Definicin de variables
Compartenvariaspropiedadescon
losatributos:
DataType:aunquenotodotipodedatos
vlidoparaatributotambinloespara
variable(ej:Blob)yviceversa(ej:tiposde
datosestructurados).
F4
Based On
Ofrece una forma rpida de definir una variable. Cuando se selecciona, se despliega un dilogo que muestra
todos los atributos (y dominios) definidos en la base de conocimiento; en dicho dilogo, simplemente se debe
seleccionar un atributo, y a continuacin se definir automticamente una variable con el mismo nombre y la
misma definicin que el atributo.
Por otra parte, es posible definir variables dentro del editor de cdigo de cada objeto (source, eventos, etc.),
haciendo uso del men contextual (botn derecho) luego de escribir el nombre de la variable. Esto es, al
escribir &nombreDeVariable y presionar botn derecho del mouse. En el men contextual luego elegir Add
Variable.
Variables coleccin
Es posible definir variables coleccin sobre cualquier tipo de datos ofrecido por GeneXus.
Para eso alcanza con clickear la correspondiente casilla en el editor de variables, o indicar el valor True en la
propiedad Collection asociada a las variables.
Para recorrer luego los items coleccionados en dicha variable, se deber utilizar la estructura de control For
in.
Por ejemplo, hemos definido la variable &myNumbers de tipo Numeric(4.0)
Para recorrer los valores almacenados se deber crear una nueva variable de tipo Numeric(4.0). Creamos
entonces la variable &OneNumber, y declaramos:
For &OneNumber in &myNumbers
---------Endfor
49
Transacciones
Dominios
Objetivo: Realizar definiciones genricas.
Cundo debemos usar dominios?
Atributos y/o variables con la misma definicin.
Ejemplo:
Atributos
ProductPrice
InvoiceDetailAmount
Precio de producto
Importe total de lnea
Dominios
Es comn tener en una base de conocimiento atributos que comparten definiciones similares pero que no tienen
relacin entre s. Por ejemplo, es comn definir todos los nombres como atributos de tipo character y largo 20; o
todos los importes, como atributos de tipo numrico y largo 10.2.
El objetivo de los dominios es permitir realizar definiciones genricas. A modo de ejemplo, el atributo
InvoiceDetailAmount es de tipo numrico y largo 10.2, y al mismo tiempo, el atributo ProductPrice es del mismo
tipo y largo, en la misma base de conocimiento. De modo que podramos definir un dominio de nombre Price, que
sea de tipo numrico con largo 10.2, y luego uno Amount de tipo de datos el dominio Price anterior; a cada uno
de los atributos anteriores le asignaramos estos dominios. La ventaja de hacerlo as es que si en el futuro surge
la necesidad de cambiar la definicin de los atributos que representan importes, haramos el cambio una sola vez
(en el dominio Price), propagndose ste automticamente a los atributos InvoiceDetailAmount y ProductPrice.
50
Transacciones
Dominios
Dominios enumerados: queremosmantenerelestadodelcliente:Active,
OnHold,Closed dominioStatus
Existe la posibilidad de trabajar con dominios enumerados (aquellos que representan valores finitos y
particulares. Son muy conocidos en los lenguajes de programacin. El caso de uso tpico es para los das de la
semana: cuando se necesita que una variable tome uno de los siguientes valores: Lunes, Martes, Mircoles,
Jueves, Viernes, Sbado, Domingo).
En nuestro caso, agregaremos a la estructura de la transaccin Customer, un atributo que representa el estado
del cliente en el sistema en un momento dado. Puede estar active, on hold o closed.
Una forma de representarlo es definiendo un dominio Status, que corresponde al tipo de datos Character(1) pero
para el que decimos explcitamente que no queremos que pueda tomar todos los valores de ese tipo de datos,
sino solo 3: A, H y C, y adems le decimos que queremos trabajar dndole nombres a estos 3 valores y trabajar
con sus nombres. As, a A le asociamos el nombre Active, a H OnHold y a C Closed.
Al asociarle al atributo CustomerStatus el dominio Status (observar que GeneXus automticamente lo sugiere al
ingresar el atributo en la estructura luego de haber definido el dominio, debido a la terminacin del nombre del
atributo) internamente en el atributo de la tabla se guardar uno de los 3 valores: A, H o C, pero nosotros no
tendremos que recordar esos valores, sino sus cdigos: Active, OnHold y Closed.
Ya tenamos otro atributo con dominio enumerado: CustomerGender. En ese caso se compona de solamente 2
valores: Female y Male.
Observar cmo el Control Info ofrece para ControlType un Combo Box en lugar de un Edit. Esto tomar sentido
cuando veamos el Form de una transaccin un poco ms adelante.
51
Transacciones
Dominios
As como podemos asociarle a un atributo un dominio (y a otro dominio), tambin lo podemos hacer para una
variable. Un mismo dominio puede asignarse tanto a atributos como a variables, ya que su objetivo es
exactamente el mismo.
Cmo definir un dominio?
Existen varios caminos:
1) Opcin Domains de el Folder View: Mediante un editor similar al de las variables, se podr definir un nuevo
dominio.
2) Dado que en la pantalla de configuracin de las propiedades de un atributo es donde se le asigna a un atributo
un dominio existente, en dicha pantalla se ofrece un botn para crear un dominio nuevo. dem con el dilogo de
definicin de variables.
3) En la estructura de la transaccin es posible definir un nuevo domino en el campo de definicin del tipo de
datos de un atributo, simplemente escribiendo sobre esa misma lnea, el nombre del dominio, y asignndole el
tipo de datos. Por ejemplo, digitando Price = Numeric(10.2) sobre la columna Type del atributo que se est
definiendo, queda tambin definido el dominio de nombre Price, con el tipo de datos Numeric(10.2).
52
Transacciones
Web Form
Para cada transaccin, GeneXus crea un form web, que ser la interfaz con el usuario.
Es creado por defecto por GeneXus al momento de grabar la estructura de la transaccin, y contienen
todos los atributos incluidos en la misma, con sus respectivas descripciones, adems de algunos botones.
Si bien es creado por defecto, es posible modificarlo para dejarlo ms vistoso, cambiar por ejemplo
controles de tipo edit a otros tipos de controles, agregar y/o quitar botones, etc.
53
Transacciones
Web Form de la transaccin Invoice
Control Error Viewer
GRID
En el ejemplo se muestra el form Web correspondiente a la transaccin Invoice. A travs de este form el usuario
final podr ingresar, modificar y eliminar facturas en la aplicacin Web.
El control Error Viewer se utiliza para poder ubicar y programar el lugar donde queremos que los mensajes
generales le sean desplegados al usuario final de una transaccin Web.
Podremos especificar entre otras cosas el lugar donde queremos que este control se ubique dentro del form, su
tipo de letra, color, etc.
Observar que el segundo nivel de la transaccin aparece en el form como un control grid.
54
Transacciones
Web Form de la transaccin Customer
Dominios bsicos
controles Edit
Dominios enumerados
controles Combo Box
55
Transacciones
Paletas de herramientas para el diseo de Forms
Insertar controles:
Opcin View de la Menubar \ Other Tool Windows \
Toolbox
Podemos definir un control como un rea de la interfaz con el usuario, que tiene una forma y un
comportamiento determinado.
Existen distintos controles:
- Texto: Permite colocar texto fijo
- Atributo/Variable: Permite colocar atributos o variables.
- Lnea horizontal
- Error Viewer
- Table: Insertar tablas en el form
- Grid: Permite definir grillas de datos.
- Botn: Permite incluir botones en los forms.
- Bitmap: Permite definir bitmaps estticos, etc.
Paleta de herramientas para insertar controles: Cuando se est editando un form, se encuentra disponible
una paleta de herramientas (Toolbox) que ofrece los controles posibles de insertar en el mismo. Simplemente
se deber seleccionar el control y arrastrarlo sobre el form.
56
Transacciones
Controles en Web Form
Cada control del Web form podr tener una clase asociada, de un
objeto theme (tema) determinado, asociado al objeto.
Para lograr separar los aspectos de diseo grfico de un sitio web, de los aspectos de programacin
propiamente dichos, existe un tipo de objeto llamado Theme (Tema, en espaol).
El objetivo de esta separacin es poder paralelizar el desarrollo de un sitio Web, permitindole al
programador abocarse a las tareas de programacin, y apoyarse en un diseador grfico para que defina
las cuestiones de diseo. De esta manera el diseador grfico configurar el tema elegido por el
programador, y el programador slo deber aplicarlo a los objetos de su base de conocimiento.
Un objeto tema contendr un conjunto de clases, para cada tipo de control de los que pueden aparecer en
el form Web de un objeto GeneXus. Por ejemplo, tendr varias clases para el control botn, algunas para el
control atributo, una clase para el control Error Viewer, etc.
Cuando se crea una base de conocimiento, automticamente aparecer dentro del Folder View la carpeta
Customization con objetos Theme predefinidos que podrn importarse en la KB. Por defecto se importa el
de nombre GeneXusX. Este tema contiene un conjunto de clases asociadas a los distintos controles
existentes.
Los objetos con form Web que se vayan creando tendrn por defecto asociado este Theme, y cada control
que aparezca en sus forms tendr asociado una clase de ese tema, para este control.
57
Transacciones
Controles en Web Form
De este modo, cuando el analista crea la transaccin Customer e ingresa su estructura, al grabar podr
apreciar que el form Web tendr automticamente el aspecto que se muestra en la pantalla de arriba a la
izquierda. Quin dio formato a todos los controles si no lo hizo el analista explcitamente?
Pues bien, todas las transacciones tendrn asociado por defecto el theme GeneXusX y todos los
controles que se coloquen en el form, tendrn clases de este tema asociadas.
Si sobre el Text Block (control de texto) que se muestra arriba (Name), se editan sus propiedades (F4), se
puede observar la propiedad Class, que tiene configurada la clase TextBlock. Esta propiedad puede ser
cambiada por el analista. Al cliquear el combo box podremos ver una lista de clases posibles para ese
control (son las que figuran en el tema asociado). A la derecha hemos cambiado la clase por una de
nombre Title y en el form podemos ver la repercusin en el diseo del TextBlock.
No entraremos en detalle en este tema en el presente curso.
58
Demo
Cmo ejecutar la aplicacin?
Opcin Build \ Run Developer Menu, o presionar la tecla F5.
F5: Dispara
automticamente
todas las acciones
necesarias para
ejecutar la aplicacin
Si BD no existe, se
crea automticamente
(siempre y cuando
usuario y password
tengan permisos de
DBCreator)
Recordemos que al momento de creacin de la KB, se indic el generador por defecto a utilizar. Ahora
se debe completar la informacin necesaria para terminar de definir el ambiente de implementacin.
Database name: Nombre de la base de datos que estar asociada a la aplicacin.
Server name: Nombre del servidor de base de datos que la manejar.
Use trusted connection: Yes
No (deber indicarse usuario y contrasea vlido en el DBMS)
Consideraciones:
Si la base de datos no existiera, GeneXus la crear, siempre y cuando el usuario y contrasea
configurados en la ventana de dilogo tengan permiso de DBCreator en el DBMS.
59
Proceso de Build
El proceso de Build incluye todas las tareas necesarias para la ejecucin
de la aplicacin: Verificacin de cambios en la BD, Reorganizacin (si es
necesario), Especificacin, Generacin y Compilacin. No incluye la
ejecucin.
KB
REORGANIZATION
DBASE IMPACT
ANALYSIS
SPECIFICATION
GENERATION
COMPILATION
Aplicacin pronta
para ejecutar
APPLICATION
Cada vez que se ejecuta la aplicacin (F5), GeneXus realiza una comparacin entre las definiciones actuales
de todos los objetos y las definiciones de la ltima ejecucin. Esta comparacin se llama anlisis de impacto.
Este nombre es autodescriptivo: GeneXus analiza el impacto causado por las nuevas definiciones, y el
resultado del anlisis de impacto es un reporte de anlisis de impacto (IAR: Impact Analisis Report) que
informa al programador qu cambios fsicos o estructurales habra que realizar en la base de datos asociada.
Si por ejemplo se cre una nueva transaccin, esto provocar (tal como es el objetivo de las transacciones)
que se creen las tablas correspondientes en la base de datos (ver siguiente pgina).
60
IAR y Reorganizacin
Create si est todo OK se
construirn los programas en el
Environment y se ejecutar...
En el ejemplo, tras crear las 2 transacciones Customer e Invoice y dar F5, aparece el reporte de anlisis de
impacto que puede verse, donde se listan entre otras cosas, la estructura que tendr cada tabla que se crear,
con sus atributos, tipos de datos, los ndices que se crearn sobre las tablas, las claves forneas (observar que
el reporte de la tabla INVOICE dice que se referenciar la tabla CUSTOMER (esto se debe al atributo
CustomerId de la transaccin Invoice que se llama igual que el atributo CustomerId de CUSTOMER,
constituyendo por tanto una clave fornea a dicha tabla).
Si el programador est de acuerdo con los cambios estructurales informados en el reporte de anlisis de
impacto, podr proseguir, pasando a reorganizar la base de datos. El trmino reorganizar refiere a efectuar
cambios fsicos en la base de datos.
Si en cambio el programador encuentra que algo de lo informado en el reporte de anlisis de impacto no era lo
que pretenda lograr, podr no efectuar la reorganizacin, y efectuar en cambio las redefiniciones que crea
convenientes.
Cuando se decide efectuar una reorganizacin GeneXus genera programas (en el lenguaje elegido cuando se
cre la KB) que implementan las modificaciones a realizar en la base de datos. La ejecucin de estos
programas tiene por resultado la obtencin de una nueva versin de la base de datos con los cambios
efectuados.
El siguiente paso ser obtener los programas de aplicacin asociados a los objetos GeneXus. Para ello
GeneXus deber especificar, generar y compilar los programas de aplicacin.
Especificar un objeto significa que GeneXus analizar todo lo definido en cada uno de los elementos que lo
componen: estructura, forms, u otros elementos segn corresponda. GeneXus verificar la sintaxis de las
definiciones, la validez de lo definido, y como resultado de la especificacin mostrar al usuario un listado de
navegacin, en el cual informar la lgica que ha interpretado, y si hay alguna advertencia o error.
Generar un objeto, significa que GeneXus escribir lneas de cdigo que implementen la programacin del
mismo, en el lenguaje elegido.
Compilar los programas significa que el cdigo escrito (generado) sea convertido a lenguaje mquina (binario)
para que puedan ser ejecutados.
61
Ejecucin
62
63
Build / Rebuild / Run options: Opciones que aplican a objetos definidos como Main. Disparan las siguientes
acciones:
- Salvan los objetos que no estn salvados.
- Reorganizan la base de datos, si es necesario.
- Se especifican solamente los objetos que sufrieron cambios (si se seleccion Build), o se
fuerza la especificacin de todos los objetos pertenecientes al rbol de llamadas del
objeto Main (si se seleccion Rebuild).
- Generacin
- Compilacin del objeto Main
- Ejecucin del objeto Main (si se seleccion la opcin Run)
Build / Run with this only options: Build y ejecucin del objeto definido como Startup. Por defecto el objeto
Startup es el Developer Menu.
- Salvan todos objetos que no estn salvados.
- Reorganizan la base de datos, si es necesario.
- Especifican solamente el objeto seleccionado.
- Generan solamente el objeto seleccionado.
- Compilan el objeto Startup
- Se ejecuta el objeto Startup (si se seleccion Run).
Set As Startup Object: El objeto indicado pasar a ser el objeto Startup de la aplicacin, o sea el objeto que
finalmente se ejecutar cuando se presione la tecla F5. Por defecto el objeto Startup es el Developer Menu.
Create Database Tables: Crea nuevamente las tablas. Se pierden los datos que pudieran estar almacenados
previamente.
Impact Database Tables: Se realiza un impacto sobre las tablas de la base de datos.
64
Transacciones
Modos en tiempo de ejecucin
Al ejecutar una transaccin se pueden distinguir los siguientes
modos, dependiendo de la operacin que se realice:
Modo Insert: Indica que se est efectuando una insercin
Modo Update: Indica que se est efectuando una actualizacin
Modo Delete: Indica que se est efectuando una eliminacin
Modo Display: Indica que se est efectuando una consulta
65
Transacciones
En tiempo de ejecucin
&GxRemove:
Variable del
sistema para
eliminar
lneas.
Siempre se mostrar un nmero de lneas vacas fijas para ser ingresadas por el usuario (valor
configurable por el analista a nivel del grid, en su propiedad Rows). Por defecto se muestran 5
lneas vacas.
Si el usuario ingres las 5 lneas y necesita ingresar ms, le bastar con presionar New Row., o
simplemente presionar Enter y se agregar una nueva lnea.
Para poder eliminar lneas en ejecucin, GeneXus incorpora automticamente en el grid del form
Web una primera columna conformada una variable del sistema de nombre &GxRemove, en forma de
check box. Para visualizar este check box, se debe presionar el botn derecho del mouse sobre la
lnea a eliminar. Luego se deber presionar el botn Confirm.
66
Transacciones
Master Pages
Las Master Pages proveen una forma de centralizar el layout y el
comportamiento comn en un solo objeto y reutilizarlo en todo otro
objeto sin tener que programar.
Creadas automticamente
con la KB
Tener un look & feel consistente es hoy en da un deber de toda aplicacin Web.
Crear y mantener cada pgina de una aplicacin Web asegurando la consistencia con el resto del sitio toma
gran tiempo de programacin.
Al crear una base de conocimiento GeneXus X crear tambin dos objetos de tipo Master Page:
AppMasterPage: Para la aplicacin.
PromptMasterPage: Para los prompts.
Las Master Pages proveen una forma de centralizar el layout y el comportamiento comn en un solo objeto y
reutilizarlo en todo otro objeto sin tener que programar. Esto significa que la modificacin de alguna parte del
layout o del comportamiento comn es tan fcil como modificarla en un nico objeto y listo!.
En una misma base de conocimiento se pueden definir tantas Master Pages como se desee.
Cuando estudiemos el objeto Web Panel comprenderemos que una Master Page ser en particular un Web
Panel categorizado como Master Page con todo lo que sea el Layout y comportamiento comn a todas las
pginas del sitio; dentro de este objeto se dejar un espacio para cargar en cada oportunidad la pgina que
corresponda (el contenido variable del sitio). Eso se har en el control presente en el form de nombre Content
Placeholder.
67
Transacciones
Master Pages
Propiedad Master Page
Las pginas web que implementan el contenido variable, se asocian a la Master Page, de manera que cada
vez que se ejecuten, se carguen con ese contexto (el de la Master Page).
68
Demo
AgregarlatransaccinProduct faltanteyvercmose
modificanlosconosenInvoice
Obsrvese cmo luego de crear la transaccin Product GeneXus normaliza e indica grficamente en la
estructura de la transaccin Invoice que los atributos, antes propios de la tabla INVOICEDETAIL, ahora sern
inferidos, a travs de la nueva clave fornea ProductId.
La clave primaria de la tabla INVOICEDETAIL seguir siendo compuesta: {InvoiceId, ProductId}, pero adems,
el atributo ProductId slo, ser una FK a la tabla PRODUCT, a partir del cul se inferirn los atributos
ProductDescription y ProductPrice.
Luego del F5, naturalmente se informar de la necesidad de reorganizar la base de datos, crendose la tabla
PRODUCT y modificndose la tabla INVOICEDETAIL de la manera que indicamos en los prrafos anteriores.
Qu pasar con los registros ya existentes en la tabla INVOICEDETAIL, para los que existan valores de
ProductDescription y ProductPrice?
Como se ver cuando se ejecute, el programa de reorganizacin agrega una rutina para crear los registros de
productos en la tabla PRODUCT con esa informacin pre-existente. Qu pasar si exista el mismo producto
en varias lneas de distintas facturas?
69
Integridad referencial
70
Integridad Referencial
Diagramas
COUNTRY
1
CountryId*
CountryName
CUSTOMER
CustomerId*
CustomerName
CountryId
El concepto de integridad referencial es un concepto que tiene que ver con las bases de datos
relacionales.
Se refiere a que debe haber consistencia entre los datos de las distintas tablas de una base de datos
relacional.
Las tablas de una base de datos relacional se encuentran relacionadas por atributos que tienen en
comn. Estas relaciones implican que los datos de las tablas no son independientes, sino que al
insertar, modificar y eliminar registros en una tabla, se deben tener en cuenta los datos de las otras
tablas para que siempre se conserve la consistencia de la informacin en la base de datos.
Si tenemos un modelo de datos relacional con las tablas:
COUNTRY (CountryId, CountryName)
Clave Primaria: CountryId
CUSTOMER (CustomerId, CustomerName, CountryId, CustomerAddress, CustomerGender,
CustomerStatus)
Clave Primaria: CustomerId
Clave Fornea: CountryId (COUNTRY)
El hecho de que el atributo CountryId en la tabla CUSTOMER sea una clave fornea con respecto a la
tabla COUNTRY, establece una relacin entre ambas tablas. La relacin entre ellas puede verse en el
diagrama que mostramos arriba.
En dicho diagrama, la flecha simple representa la existencia de una instancia de la tabla apuntada,
para cada instancia de la otra (es decir, que para cada cliente existe un y solo un pas). La flecha doble
representa la ocurrencia de varias instancias de la tabla apuntada, para cada instancia de la otra tabla
(es decir, que para cada pas, existen muchos clientes).
Se dice que la relacin entre la tabla COUNTRY y la tabla CUSTOMER es 1 a N (1 a muchos).
Recprocamente, la relacin entre CUSTOMER y COUNTRY es N a 1 (muchos a 1).
71
Integridad Referencial
Diagramas
Hay que verificar existencia del COUNTRY referenciado.
COUNTRY
1
N
CUSTOMER
COUNTRY
En transaccin Customer:
si se inserta nuevo registro, o
si se modifica el CountryId de un registro
En transaccin Country:
si se quiere eliminar un registro
1
N
CUSTOMER
En la terminologa GeneXus, decimos que existe una relacin de subordinacin entre ambas tablas.
Decimos que:
COUNTRY est superordinada a CUSTOMER
CUSTOMER est subordinada a COUNTRY
Significando que:
Cuando se crea o modifica un registro en la tabla subordinada (CUSTOMER), debe existir el
registro relacionado en la tabla superordinada (COUNTRY).
Cuando se elimina un registro en la tabla superordinada (COUNTRY), no deben existir registros
relacionados en la tabla subordinada (CUSTOMER).
Debido a esta relacin entre las tablas, la informacin contenida en ellas no es independiente, y es
necesario realizar controles para que los datos sean consistentes. A estos controles se les llama de
Integridad Referencial y bsicamente son los siguientes:
Cuando se inserta o modifica un registro en la tabla CUSTOMER, el valor ingresado en el atributo
que es clave fornea (CountryId), debe existir como valor de clave primaria de un registro en la tabla
COUNTRY.
Cuando se elimina un registro en la tabla COUNTRY, no deben existir registros en la tabla
CUSTOMER cuyos valores de la clave fornea (CountryId), sean iguales al valor de la clave primaria
del registro que se desea eliminar.
GeneXus genera los programas asociados a las transacciones, incluyendo en el cdigo generado
estos controles de Integridad Referencial. Por esta razn, si el usuario final inserta (o modifica) un
cliente a travs de la transaccin "Customer", se validar automticamente que el valor ingresado en el
cdigo de pas CountryId, exista como clave primaria de un registro en la tabla COUNTRY. En caso de
fallar este control de integridad referencial, un mensaje se le desplegar al usuario indicndole que no
se encontr ese pas.
72
Integridad Referencial
Indices
73
Integridad Referencial
Indices primarios y forneos
CountryId*
CountryName
PK
ICountry
CountryId CountryName
1
2
3
Uruguay
United States
China
Si en transaccin Country
queremos eliminar United
States:
PK
ICustomer
CustomerId*
CustomerName
...
FK ICustomer1
CountryId
CustomerId
4
1
3
2
CustomerName
Ann Silver
John Smith
Mary Jones
Jessica Deep
CountryId
1
1
1
2
Por existir esta relacin, GeneXus incluye en los programas asociados a las transacciones "Country" y
"Customer", los controles de integridad referencial pertinentes. Estos controles son:
Si el usuario final inserta o modifica un cliente a travs de la transaccin "Customer", se validar
automticamente que el valor ingresado en la clave fornea CountryId exista como clave primaria de un
registro en la tabla COUNTRY. En caso de fallar este control de integridad referencial, se le indicar al
usuario que no se encontr ese pas.
Para controlar esto, se debe buscar en la tabla COUNTRY la existencia de un registro que tenga ese
valor de CountryId como clave primaria; dado que se debe consultar la tabla COUNTRY, buscando por la
clave primaria, resulta evidente que la bsqueda puede optimizarse si existe un ndice por la clave
primaria en dicha tabla.
Si el usuario final intenta dar de baja un pas a travs de la transaccin Country, se validar
automticamente que no existan clientes con dicho pas asociado, como clave fornea; en caso de
encontrar un registro en la tabla CUSTOMER, cuyo valor de clave fornea CountryId sea el que se desea
eliminar, se le indicar al usuario que no es posible eliminar el pas (ya que de lo contrario quedaran
datos inconsistentes en la base de datos).
Para controlar esto se debe consultar la tabla CUSTOMER, buscando por la clave fornea CountryId.
Esta bsqueda ser ptima si existe un ndice por CountryId en la misma.
Control de unicidad de clave primaria
Otro control que GeneXus tambin incluye en los programas asociados a las transacciones es la unicidad
de la clave primaria; esto es, en ninguna tabla podrn existir dos registros con el mismo valor en la clave
primaria.
Para controlar esto, cuando el usuario final intenta insertar un registro se valida automticamente que el
valor ingresado para la clave primaria no exista ya como clave primaria de otro registro en la tabla.
Para hacer esta bsqueda con eficiencia, se debe utilizar el ndice primario de la tabla.
Concluyendo, GeneXus al crear cada tabla de la base de datos crea tambin su ndice primario, y un
ndice forneo por cada clave fornea que la tabla contenga.
La creacin de estos ndices permite realizar los controles de integridad referencial y de unicidad
de clave primaria accediendo a las tablas de forma eficiente.
74
Integridad Referencial
Indices de Usuario
Los crea el analista sobre una tabla. Deber categorizarlos segn si
aceptar valores repetidos (duplicate) o no (unique).
CustomerId
CustomerName
1
2
3
Ann
Ann
Mary
CountryId
1
2
1
ndices de usuario
Estos ndices deben ser definidos explcitamente por el analista. No son definidos
automticamente. Se dividen en duplicate y unique.
Un ndice de usuario duplicate es aquel que se define para atributos de una tabla para los que
pueden existir varios registros con el mismo valor en los mismos (es decir, se define para atributos
que no son una clave candidata).
Este tipo de ndices se define fundamentalmente para acceder a los datos ordenados por
determinados atributos de forma eficiente.
A modo de ejemplo, suponiendo que el nombre de cliente no es clave en la tabla CUSTOMER (sus
valores se pueden repetir) podremos definir un ndice de usuario duplicate por el atributo
CustomerName, siendo muy til para realizar consultas y listados que se necesite salgan ordenados
por nombre.
Un ndice de usuario unique se utiliza para especificar que un conjunto de atributos es clave
candidata en una tabla (diferente de la clave primaria).
Esta es la forma de representar claves candidatas en el modelo de datos. Con ello logramos que
GeneXus incorpore automticamente el control de unicidad correspondiente en las transacciones
asociadas.
A modo de ejemplo, si el nombre de cliente no se puede repetir, la forma de representarlo y lograr
que GeneXus lo controle automticamente es definiendo en la tabla CUSTOMER un ndice de
usuario unique por el atributo CustomerName.
75
Integridad Referencial
Indices de Usuario
Si un mismo nombre no puede repetirse (es por tanto un atributo
clave de la tabla)
CustomerId
1
2
3
CustomerName
John Smith
Ann Jones
Richard Land
CountryId
1
2
1
76
Integridad Referencial
Indices Temporales
Son creados automticamente, bajo ciertas condiciones, cuando
son necesarios, y se eliminan cuando termina la ejecucin del objeto
que los cre.
Si se desea acceder a los datos ordenados por determinados
atributos, pero no se desea crear un ndice permanente para ello:
GeneXus crear un ndice temporal.
En algunas plataformas, las consultas para las cuales se quiere
obtener el resultado ordenado por determinados atributos, y no
existe el ndice de usuario, son resueltas por el DBMS
correspondiente sin la creacin de ndices temporales.
El usuario puede resolver dejar de utilizar un ndice temporal,
creando un ndice de usuario.
ndices temporales
Si se desea acceder a los datos ordenados por determinados atributos, pero no se desea crear un
ndice permanente para ello (por ejemplo, porque se trata de una consulta que se realiza con muy
poca frecuencia), entonces, dependiendo de la plataforma, se crear un ndice temporal.
77
Integridad Referencial
Manejo de nulos
La permisin o no del valor <NULL> en la base de datos es muy importante en el modelo relacional.
Permitir el valor null para un atributo dado, significa que puede, bajo ciertas circunstancias, ser
ignorado dado que es valor no especificado. Por otro lado, si un atributo no permite valor null, un valor
vlido siempre deber asignarse a l.
La propiedad Nulls (presentada como columna en el editor de estructuras de transacciones), permite
configurar para cada atributo si admite o no valor null en la tabla asociada. Los atributos para los cuales
puede configurarse esto, es para aquellos almacenados en la(s) tabla(s) asociada(s) a la transaccin (es
decir, no inferidos) siempre y cuando no sean atributos primarios en dichas tablas (ya que por definicin
las claves primarias no soportan valor null).
Resumiendo: el objetivo de esta propiedad es definir qu valor se va a almacenar en la base de datos
cuando no digitemos nada en el campo (el valor <NULL> o el valor empty).
78
Integridad Referencial
Manejo de nulos
Valores posibles que ofrece la propiedad Nulls:
- No: Valor por defecto. El atributo en la tabla asociada, no
permitir valor null
- Yes: el atributo en la tabla asociada, s admitir valor null
79
Integridad Referencial
Manejo de nulos
CountryId*
CountryName
CountryId*
CityId*
CityName
FK
compuesta
CustomerId*
CustomerName
CountryId
CityId
80
Integridad Referencial
Manejo de nulos
Diferencia entre valor empty y null para atributos:
empty: es un valor (0 para Numeric, para Character, etc.)
null: si est permitido, no es un valor. Significa que el valor debe
ser considerado como:
no especificado
no disponible
no asignado
desconocido
IsEmpty
IsNull
SetEmpty
SetNull
81
Tabla base
y
Tabla extendida
82
Los criterios de normalizacin del diseo de la base de datos apuntan a minimizar la posibilidad de
inconsistencia en los datos. Una base de datos diseada de esta manera tiene una serie de ventajas
importantes (tal es as que actualmente la normalizacin de datos es un estndar de diseo), pero se
deben tener en cuenta tambin algunos inconvenientes.
El inconveniente ms notorio es que los datos se encuentran dispersos en muchas tablas, y por lo
tanto cuando se quieren hacer consultas ms o menos complejas a la base de datos, se debe
consultar una cantidad importante de tablas.
As, por ejemplo, si el siguiente diagrama representa nuestro modelo de datos:
para listar las facturas sera necesario consultar las tablas: INVOICE e INVOICEDETAIL (lneas de
Facturas), CUSTOMER, COUNTRY y PRODUCT.
Para simplificar esta tarea GeneXus utiliza el concepto de tabla extendida.
Llamamos tabla base a cualquier tabla de la base de datos en la cual estemos posicionados en
determinado momento; y dada cierta tabla base, su tabla extendida comprender a todos los
atributos de la propia tabla base, ms todos los atributos de las tablas que tengan informacin
relacionada unvocamente con la tabla base (relacin N-1 desde la tabla base, directa e
indirectamente).
83
INVOICEDETAIL
InvoiceId*
ProductId*
InvoiceDetailQuantity
InvoiceDetailAmount
CUSTOMER
COUNTRY
CustomerId*
CustomerName
CountryId
CustomerGender
CustomerStatus
CountryId*
CountryName
PRODUCT
ProductId*
ProductDescription
ProductPrice
ProductStock
Utilizando el diagrama es fcil determinar cul es la tabla extendida correspondiente a una tabla
base cualquiera:
Partiendo de la tabla base, se deben seguir las relaciones N-1, (es decir, se deben seguir las flechas
que tienen punta doble partiendo desde la tabla base, y punta simple en el otro extremo).
Todas las tablas a las cuales se pueda llegar siguiendo las flechas que representan relaciones N-1
desde la tabla base, formarn parte de su tabla extendida.
El siguiente cuadro muestra la tabla extendida correspondiente a cada una de las tablas de nuestro
modelo de datos:
84
Reglas
Se utilizan para definir el comportamiento de las transacciones.
Algunas reglas:
Default
Asignacin
Msg
Error
Noaccept
Add
Subtract
Serial
Update
Las reglas, en el objeto transaccin, cumplen un rol muy importante ya que permiten programar su
comportamiento (por ejemplo: asignar valores por defecto, definir controles sobre los datos, etc.).
Se escriben de forma declarativa, es decir que el orden en el que se escriben no significa que sea el
orden en el que se ejecutarn.
Pueden involucrar a los atributos definidos en la estructura de la transaccin1, as como a
variables definidas dentro del objeto, constantes y funciones.
Son solo vlidas dentro de la transaccin en la que estn definidas, es decir, son locales.
-------------------------------------------------------------------------------------------------------1 Todas las reglas de transacciones pueden involucrar atributos de las tablas base asociadas a la transaccin; y la
mayor parte de ellas puede tambin involucrar atributos de las tablas extendidas de dichas tablas base. Para poder
referenciar un atributo en una regla, el mismo deber estar incluido en la estructura de la transaccin (ya sea que
pertenezca a alguna de las tablas base asociadas a la transaccin, o a sus tablas extendidas).
85
Default
OBJETIVO: Permite asignar un valor por defecto a un atributo o variable; el valor por defecto inicializar al atributo o
variable si se est realizando una insercin por medio de la transaccin (modo Insert), pero el usuario final podr
cambiarlo si ese valor no es el que desea.
SINTAXIS: Default( att | &var, exp );
DONDE:
att: es un atributo perteneciente a alguna de las tablas base asociadas a la transaccin.
var: es el nombre de una variable.
exp: es una expresin que puede involucrar constantes, funciones, variables u otros atributos.
FUNCIONALIDAD: Esta regla asigna el valor de la expresin exp como valor por defecto del atributo att o variable var,
cuando la transaccin se ejecuta en modo Insert.
Esta regla no es vlida para atributos que forman parte de la clave primaria de alguno de los niveles de la transaccin,
porque es disparada luego de que la clave es ingresada (ya que solo en ese momento el modo es conocido y esta regla
se dispara solo en modo Insert).
EJEMPLOS:
Default( InvoiceDate, &today );
Cuando se est insertando una factura nueva, se sugiere como valor de InvoiceDate el valor contenido en la variable del
sistema today.
Default( InvoiceDate, Today());
Anloga a la anterior, solo que en lugar de utilizar la variable del sistema today, se utiliza la funcin Today que devuelve
la fecha correspondiente al da.
Default( InvoiceDetailAmount, ProductPrice*InvoiceDetailQuantity); /* Regla definida en Invoice */
Cuando se est insertando una lnea de factura, se sugiere que el atributo InvoiceDetailAmount (importe de la lnea)
tome el valor resultante de evaluar la expresin ProductPrice*InvoiceDetailQuantity (precio del producto por cantidad
llevada del mismo).
Nota: El tipo de datos de la expresin debe coincidir con el tipo de datos del atributo o variable
Regla de asignacin
OBJETIVO: Permite asignar a un atributo o a una variable, el valor de una expresin.
SINTAXIS: att | &var = exp [if cond] [on evento/momento de disparo];
DONDE:
att: es un atributo perteneciente a alguna de las tablas base asociadas a la transaccin, o a sus tablas extendidas
(debe estar declarado en la estructura).
var: es el nombre de una variable.
exp: es una expresin que puede involucrar constantes, funciones, variables u otros atributos, y debe ser del mismo
tipo que att o var.
cond: es una expresin booleana (puede contener los operadores lgicos and, or, not)
evento/momento de disparo: es uno de los eventos predefinidos de
GeneXus
disponibles
para
reglas
de
transacciones, que permiten definir el momento especfico de ejecucin de una regla.
FUNCIONALIDAD: Una regla de este tipo permite asignar al atributo o variable de la izquierda, el valor resultante de
evaluar la expresin. Como puede verse, la condicin es opcional; de no ponerla, la asignacin se realiza siempre.
La asignacin a un atributo, implica su actualizacin en el registro que corresponda. Se pueden definir reglas de
asignacin a atributos de alguna de las tablas bases asociadas a la transaccin, e incluso de sus tablas extendidas.
Esto significa que pueden actualizarse atributos inferidos en una transaccin (siendo necesario declararlos en la
estructura).
86
EJEMPLO:
InvoiceDetailAmount = ProductPrice*InvoiceDetailQuantity; /*Regla definida en la transaccin Invoice*/
Si el importe de cada lnea de una factura se calcula siempre multiplicando el precio del producto por la cantidad llevada del
mismo, podemos utilizar esta regla de asignacin para liberar al usuario de realizar el clculo.
Error
OBJETIVO: Permite desplegar un mensaje de error si la condicin se satisface. Sirve para definir los controles que deben
cumplir los datos.
SINTAXIS: Error( msg | &var | character expresion, msgId ) if cond [on evento/momento de disparo];
DONDE:
msg: es un string con un mensaje de error a desplegar.
var: es el nombre de una variable de tipo character, que contiene un string con un mensaje de error a desplegar.
character expression: es una expresin cuyo tipo resultante es character y que ser desplegada.
msgId: es un string (sin espacios en blanco ni comillas) que ser utilizado solo si la transaccin es definida tambin como
business component1.
cond: es una expresin booleana (que puede contener los operadores lgicos and, or, not)
evento/momento de disparo: es uno de los eventos predefinidos de GeneXus disponibles para reglas de transacciones,
que permiten definir el momento especfico de ejecucin de una regla.
FUNCIONALIDAD: Esta regla despliega el mensaje del parmetro msg, var o character expresion, si la condicin cond que
se evala resulta verdadera. El mensaje de error se despliega en una ventana popup cuando el ambiente de trabajo es
Windows y en el control Error Viewer y/o un cuadro de texto cuando el ambiente de trabajo es Web, deteniendo cualquier
actualizacin a la base de datos. Cuando la transaccin se ejecuta como business component (estudiaremos este tema
mas adelante en el curso), de dispararse el error, generar una entrada en el SDT messages, con identificador msgId.
EJEMPLOS:
Error(No se permiten clientes sin nombre) if CustomerName.isEmpty();
/*Regla definida en la transaccin Customer*/
Se evala la condicin CustomerName.isEmpty(), y si sta se satisface, se despliega el mensaje No se permiten clientes
sin nombre en pantalla. No se permite continuar hasta que el usuario ingrese un nombre en el campo CustomerName o
abandone la transaccin (en cuyo caso no se har en la base de datos actualizacin alguna).
Error(No se permite eliminar facturas) if Delete;
/* Regla definida en la transaccin Invoice */
Se necesita prohibir la eliminacin de facturas. Con esta regla, si el usuario intenta realizar una eliminacin, la condicin
dar True y se disparar la regla, evitando la eliminacin.
Msg
OBJETIVO: Permite desplegar un mensaje de advertencia si la condicin se satisface.
SINTAXIS: Msg( msg | &var | character expresion, msgId) if cond [on evento/momento de disparo];
DONDE:
msg, var, character expresion, msgId, cond, evento/momento de disparo: son los mismos que para la regla error.
Observar que la sintaxis es exactamente la misma.
FUNCIONALIDAD: Esta regla se utiliza para presentar mensajes de advertencia al usuario. Despliega el mensaje del primer
parmetro, si la condicin se satisface, anlogamente a la regla Error; pero a diferencia de esta ltima, permite continuar
con la ejecucin si la condicin sigue satisfacindose. Del mismo modo, si la transaccin es business component1, de
dispararse la regla genera entrada en el SDT messages.
Los mensajes de advertencia se despliegan en el Error Viewer.
87
EJEMPLO:
Msg( No se permiten clientes sin nombre ) if CustomerName.isEmpty();
/*Regla definida en la transaccin Customer*/
Se evala la condicin CustomerName.isEmpty(), y si sta se satisface se despliega el mensaje No se permiten clientes sin
nombre. A diferencia de lo que ocurre con la regla Error, aqu s se permite continuar la ejecucin, pues no se trata de un
error sino de una advertencia.
Noaccept
OBJETIVO: Permite indicar que los atributos no aceptarn valores por parte del usuario (sern solo de salida).
SINTAXIS: Noaccept( att1[, atti]) [if cond];
DONDE:
atti: es un atributo perteneciente a alguna de las tablas bases asociadas a la transaccin.
cond: es una expresin booleana (puede contener los operadores lgicos and, or, not).
evento/momento de disparo: es uno de los eventos predefinidos de GeneXus disponibles para reglas de transacciones, que
permiten definir el momento especfico de ejecucin de una regla.
FUNCIONALIDAD: En una transaccin, todos los atributos que pertenecen a las tablas base asociadas a la transaccin, por
defecto son aceptados. Si queremos que algunos atributos con estas caractersticas no sean aceptados, entonces
contamos con la regla Noaccept.
EJEMPLO:
Noaccept( IvoiceDate) if Update; /* Regla definida en la transaccin Invoice */
Si se est modificando una factura (modo Update), no se permite que se modifique su fecha.
Subtract
OBJETIVO: Sustrae el valor de un atributo al valor de otro atributo, si se satisface la condicin especificada.
SINTAXIS: subtract(att1, att2) [if cond];
DONDE:
att1, att2: son atributos pertenecientes a alguna de las tablas base asociadas a la transaccin, o a sus tablas extendidas (y
deben estar declarados en la estructura)
cond: es una expresin booleana (que puede contener los operadores lgicos and, or, not).
FUNCIONALIDAD: La sustraccin se realiza teniendo en cuenta el modo en el que se est trabajando en la transaccin
(Insert, Update o Delete).
En modo:
- Insert: se le sustrae al valor del atributo att2, el valor del atributo att1
- Delete: se le suma al valor de att2, el valor del atributo att1
- Update: se le sustrae al valor del atributo att2, la diferencia entre el valor nuevo y el viejo de att1
EJEMPLO:
En la transaccin Invoice, cada vez que se ingresa una lnea con un producto que se est comprando, se debe disminuir el
stock del mismo, segn la cantidad llevada.
Esto podra hacerse en forma sencilla con la siguiente regla de asignacin:
ProductStock = ProductStock InvoiceDetailQuantity;
Si prestamos atencin, sin embargo, vemos que esta regla no nos sirve, pues no est condicionada a un modo particular,
razn por la cul se disparar tanto cuando se est insertando una nueva lnea en la factura, como cuando se est
eliminando o modificando una ya existente. Y en estos ltimos dos casos es incorrecto disparar la regla.
88
De hecho, cuando se est eliminado una lnea existente, debe realizarse la operacin contraria, es decir, se debe devolver
al stock lo que se haba quitado cuando se insert la lnea.
Lo correcto entonces, teniendo en cuenta todos los casos posibles sera tener 3 reglas:
ProductStock = ProductStock InvoiceDetailQuantity if Insert;
ProductStock = ProductStock + InvoiceDetailQuantity if Delete;
ProductStock = ProductStock + old(InvoiceDetailQuantity) InvoiceDetailQuantity if Update;
Aqu estamos utilizando la funcin old, que devuelve el valor almacenado del atributo (es el valor antes de modificarlo).
Para evitar tener que hacer todo esto, GeneXus provee la regla subtract que se encarga de hacer la asignacin correcta de
acuerdo al modo. Entonces podemos sustituir las 3 asignaciones anteriores, por:
subtract( InvoiceDetailQuantity, ProductStock);
Esta regla tiene la inteligencia para, dependiendo del modo, restar o sumar.
Add
OBJETIVO: Suma el valor de un atributo al valor de otro atributo, si se satisface la condicin especificada
SINTAXIS: add( att1, att2) [if cond];
DONDE:
att1, att2: son atributos pertenecientes a alguna de las tablas base asociadas a la transaccin, o a sus tablas extendidas (y
deben estar declarados en la estructura).
cond: es una expresin booleana.
FUNCIONALIDAD: La adicin se realiza teniendo en cuenta el modo en el que se est trabajando en la transaccin (Insert,
Update o Delete).
En modo:
- Insert: se le suma al valor del atributo att2, el valor del atributo att1
- Delete: se le sustrae al valor de att2, el valor del atributo att1
- Update: se le suma al valor del atributo att2, la diferencia entre el valor nuevo y el viejo de att1
EJEMPLO:
Definimos en la transaccin Customer, un atributo de nombre CustomerTotalPurchases, para registrar el importe total de
compras efectuadas por el mismo. El comportamiento que se desea es que cada vez que se cree una factura para un
cliente dado, se le sume el total de la factura (InvoiceAmount) al total de compras efectuadas por el cliente
(CustomerTotalPurchases).
Al igual que vimos en la regla subtract, no debemos olvidar que en la transaccin Invoice podemos tambin eliminar y
modificar facturas, y no solo crearlas; por lo tanto es importante tener en cuenta el modo de trabajo en la transaccin (Insert,
Update, Delete). GeneXus nos libera de tener que considerar nosotros a los modos, teniendo que escribir las siguientes tres
reglas de asignacin en la transaccin Invoice:
CustomerTotalPurchases = CustomerTotalPurchases + InvoiceAmount if Insert;
CustomerTotalPurchases = CustomerTotalPurchases InvoiceAmount if Delete;
CustomerTotalPurchases = CustomerTotalPurchases old(InvoiceAmount) + InvoiceAmount if Update;
y en su lugar nos provee de la regla add, que se encarga de sumar o restar, dependiendo del modo.
89
Serial
OBJETIVO: Permite numerar serialmente atributos numricos.
SINTAXIS: Serial( att1, att2, step);
DONDE:
att1: es un atributo perteneciente a alguna de las tablas base asociadas a la transaccin (es decir, no inferido),
que desea autonumerarse (debiendo estar declarado en la estructura).
att2: Tiene que pertenecer a una tabla directamente superordinada a la del atributo att1.
step: es el paso o incremento de la serializacin.
FUNCIONALIDAD: El propsito de esta regla es asignar un nmero correlativo a att1 cada vez que se inserta un
registro en la tabla a la que pertenece att1. Se toma el valor de att2 (att2 contiene el ltimo nmero utilizado en la
autonumeracin), se le suma el valor del parmetro step, y el valor resultante se asigna tanto al atributo att1 del
nuevo registro, como al atributo att2 para conservar el ltimo nmero asignado.
Es decir, cuando se est insertando un registro por medio de una transaccin en la cual se ha
definido la regla: Serial(att1, att2, step);, se accede al att2 (habr un solo valor de este atributo relacionado, pues
pertenece a una tabla directamente superordinada1), se le suma el valor step, y se asigna el valor obtenido tanto a
att1 del registro que va a ser insertado, como a att2 perteneciente a una tabla directamente superordinada con
respecto a la tabla que contiene a att1.
Si se disea a la transaccin Invoice conteniendo un Nmero de Lnea de Factura (atributo InvoiceDetailId)
como identificador nico del segundo nivel, la estructura de la transaccin sera:
Invoice
{
InvoiceId*
CustomerId
CustomerName
InvoiceDate
InvoiceLastLineId
Detail
{
InvoiceDetailId*
ProductId
ProductDescription
}
}
90
En este diseo el atributo ProductId no es identificador nico del nivel, sino clave fornea nicamente.
Cada lnea tiene un nmero de lnea que la identifica en forma nica, y es posible ingresar el mismo producto en
distintas lneas.
Podra ser til asignar por medio del sistema, nmeros correlativos al campo InvoiceDetailId, definiendo la regla:
serial(InvoiceDetailId, InvoiceLastLineId, 1);
El primer parmetro de la regla serial define cul es el atributo a numerar automticamente, en el segundo parmetro
debe indicarse un atributo cuya funcin es guardar el ltimo valor asignado hasta el momento, y por ltimo el tercer
parmetro es para indicar el incremento (en este caso se incrementa de uno en uno).
El segundo parmetro (en el ejemplo InvoiceLastLineId) debe pertenecer a una tabla directamente superordinada a la
tabla que contiene el atributo que se desea numerar automticamente (InvoiceDetailId). La regla serial lo requiere as.
En el ejemplo, se puede observar que InvoiceLastLineId se encuentra en la tabla de clave InvoiceId*, la cual es
directamente superordinada respecto a la tabla que contiene el atributo a numerar (InvoiceDetailId).
Es decir, cada factura tendr en el cabezal un atributo que almacenar el ltimo nmero de lnea asignado hasta el
momento (InvoiceLastLineId). La regla serial est implementada de forma tal que necesita este atributo (para fijarse el
ltimo nmero utilizado, sumarle el incremento, y asignar el prximo nmero a la nueva lnea).
Consideracin:
La regla serial es til a la hora de autonumerar lneas, no as cabezales (por ejemplo identificadores de facturas, de
clientes, etc.). El motivo es el siguiente: para utilizar la regla serial, se requiere definir un atributo en una tabla
directamente superordinada; esto resulta bien sencillo si se desean autonumerar lneas ya que alcanza con incluir este
atributo en el nivel de la estructura inmediatamente superior al del atributo a autonumerar.
91
Sin embargo, contamos con una solucin mucho ms simple para autonumerar cabezales: cuando una tabla tiene una clave
simple (es decir formada por un solo atributo) y el tipo de datos es numrico, puede numerarse automticamente utilizando
la funcionalidad que brindan los manejadores de base de datos para esto. La forma de indicarlo en GeneXus es
configurando la propiedad Autonumber del atributo clave:
Si en la propiedad Autonumber de un atributo numrico clave, se selecciona el valor True, significa que se realizar la
numeracin automtica del mismo. Se agregarn las siguientes propiedades en el dilogo:
Start: Mediante esta propiedad se configura a partir de qu nmero comienza la numeracin automtica.
Step: Mediante esta propiedad es posible configurar el incremento del campo (entre dos registros).
For replication: Esta propiedad es slo vlida para el motor de base de datos SQL Server; el valor Yes le indica a ste que
no debe aplicar la propiedad en caso de que la tabla sea receptora de replicacin (sino que debe mantener los nmeros que
le vienen por replicacin).
Para profundizar en el manejo de esta propiedad, recomendamos acceder al Help de GeneXus.
92
Update
OBJETIVO: Posibilita actualizar en el form de una transaccin (win/web) atributos de la tabla extendida (inferidos).
SINTAXIS: Update( att1[, atti ]);
DONDE:
atti: es un atributo perteneciente a la tabla extendida de alguna de las tablas bases asociadas a la transaccin.
FUNCIONALIDAD: En una transaccin, todos los atributos que pertenecen a las tablas base asociadas a la transaccin, por
defecto son aceptados y los que perteneciendo a la tabla extendida, no pertenecen a la base, son inferidos, y por tanto no
aceptados.
Pero si queremos que algunos de estos atributos inferidos sean aceptados, para que el usuario pueda modificar desde el
form su valor, entonces contamos con la regla Update.
EJEMPLO:
InvoiceId*
InvoiceDate
CustomerId
CustomerName
CustomerId*
CustomerName
update(CustomerName);
93
Reglas
Conceptos importantes
para
que
se
ejecuten
en
94
95
Agregar la clusula Level a una regla solamente tiene sentido si a continuacin de la misma se mencionan atributos
que son de algn nivel posterior a los niveles de los atributos implicados en la definicin de la regla en s.
En el ejemplo que sigue, el hecho de haber agregado la clusula Level a la regla no aporta ms informacin de la
ya aportada por el atributo implicado en la definicin de la regla en s:
Msg(La fecha de la factura es mayor a la fecha actual) if InvoiceDate > &Today Level CustomerId;
Es fcil comprender que el atributo InvoiceDate ya le da la pauta a GeneXus de que se trata de una regla asociada
al primer nivel, as que lo especificado por la clusula Level en el ejemplo no aporta ms informacin y por lo tanto
su agregado es innecesario.
Por ltimo, en el ejemplo que sigue:
InvoiceDetailDiscount= InvoiceDetailAmount * CustomerDiscountPercentage/100 Level InvoiceDate;
si bien se incluy la clusula Level en la definicin de la regla, como el atributo que sigue a la clusula es de un
nivel superior al nivel de los atributos referenciados en la regla, la clusula Level definida no aportar informacin
til en este caso tampoco. Es decir, no es posible que habiendo involucrados atributos de un segundo nivel en una
regla, la misma se ejecute en el primer nivel, ya que en el primer nivel no se tiene la informacin del o de los niveles
inferiores (adems de que hay N instancias para el o los niveles inferiores). De modo que la regla seguir estando
asociada al segundo nivel de la transaccin Invoice, no habiendo aportado informacin til la clusula Level en
este ejemplo.
Concluyendo, la clusula Level solamente tiene sentido que sea agregada para modificar el nivel por defecto de
disparo de una regla, a un nivel posterior.
Update
Delete
96
Frmulas
97
Frmulas
Objetivos y Definicin
Definir frmulas nos brinda una forma clave de compartir conocimiento y
obtener cdigo generado optimizado
Cuando el valor de un atributo o variable puede calcularse a partir de
otros atributos, constantes y/o funciones, puede definirse como una frmula
Contamos con 2 formas de definir frmulas:
- Globales: A nivel de la Base de Conocimiento
- Locales: En medio de cierto cdigo
Veremos este
concepto en
primer lugar
Cuando definimos una frmula, GeneXus puede combinar la consulta / clculo asociada a la frmula con la
consulta en la cual la frmula est presente y as generar sentencias optimizadas.
98
Frmulas
Globales
Frmula Global = atributo al cual el analista GeneXus le asigna un
clculo asociado.
Accediendo al
editor de
frmulas desde la
estructura de la
transaccin
99
Frmulas
Globales
Decimos que:
atributos frmula globales = atributos virtuales
Significando que:
No se crean como atributos fsicos.
Para cada objeto que referencie un atributo frmula global,
GeneXus incluir en su programa generado el cdigo necesario
para realizar el clculo y desplegarlo en tiempo de ejecucin.
Tabla base / Tabla asociada a un atributo frmula global:
Como explicamos en esta diapositiva, los atributos definidos como frmula global, no se crean como campos
fsicos en tablas, por lo cual decimos que son atributos virtuales.
Sin embargo, decimos que tienen una tabla asociada o tabla base, para conocer el contexto en el cual se
han definido, y contar con ese contexto al momento de disparar el clculo correspondiente donde sea que se
referencien.
100
Frmulas
Clasificacin
Horizontales: Una o varias expresiones aritmticas
APLICA A
GLOBALES
Y LOCALES
101
Frmulas
Clasificacin
Ejemplo de Frmula Horizontal (Global) :
Customer
{ CustomerId*
CustomerName
CustomerTotalPurchases
CustomerTotalPayments
CustomerBalance
}
CustomerTotalPurchases CustomerTotalPayments
DEJA DE PERTENECER
FSICAMENTE A LA TABLA
TABLA CUSTOMER
CustomerId*
CustomerName
CustomerTotalPurchases
CustomerTotalPayments
102
Frmulas
Clasificacin
Ejemplo II de Frmula Horizontal (Global) :
Invoice
{ InvoiceId*
CustomerId
CustomerName
InvoiceDate
Detail
{
InvoiceDetailId*
ProductId
ProductDescription
ProductPrice
InvoiceDetailQuantity
InvoiceDetailAmount
}
ProductPrice*InvoiceDetailQuantity if InvoiceDetailQuantity<=100;
}
ProductPrice*InvoiceDetailQuantity*0.9 otherwise;
En este ejemplo el atributo InvoiceDetailAmount ha sido definido como frmula global tambin. Es decir,
utilizando el editor de frmulas, se ha asociado un clculo a este atributo y el mismo pasar a ser un atributo
virtual.
La tabla asociada al atributo InvoiceDetailAmount ser INVOICEDETAIL, ya que de almacenarse dicho atributo
nuevamente, se creara en dicha tabla fsica.
Como podemos observar la frmula definida cae en la clasificacin de horizontal, ya que consiste en 2
expresiones aritmticas condicionales. Los atributos involucrados en la definicin de la frmula pertenecen o
bien a la tabla INVOICEDETAIL o bien a su tabla extendida.
103
Frmulas
Clasificacin
Ejemplos de Frmulas Aggregate (Globales) :
Invoice
{ InvoiceId*
CustomerId
CustomerName
InvoiceDate
InvoiceDetails Count(InvoiceDetailQuantity)
InvoiceAmount Sum(InvoiceDetailAmount)
Detail
{
InvoiceDetailId*
ProductId
ProductDescription
En ambos clculos solo intervienen los registros que
ProductPrice
cumplen:
InvoiceDetailQuantity
InvoiceDetailAmount
INVOICEDETAIL.InvoiceId = INVOICE.InvoiceId
}
}
En el ejemplo los atributos InvoiceDetails e InvoiceAmount han sido definidos como frmulas globales, ya que utilizando el
editor de frmulas se ha definido una frmula para cada uno de estos atributos (pasando ambos a ser atributos virtuales).
Dado que las frmulas definidas son Count y Sum respectivamente, en ambos casos se trata de frmulas Aggregate.
La tabla asociada a ambos atributos frmula es INVOICE, ya que de almacenarse estos atributos, se crearan en dicha tabla
fsica.
Las frmulas Aggregate no solo tienen una tabla base asociada (como todas las formulas), sino que tambin involucran una
tabla a ser navegada.
Si bien resulta intuitivo, la tabla a ser navegada en una frmula Aggregate, es la tabla que se navegar para realizar el
clculo. GeneXus inferir cul es la tabla a ser navegada por una frmula Aggregate, por los atributos involucrados en la
definicin de la frmula. En nuestro ejemplo, la tabla a ser navegada en ambas frmulas Aggregate es INVOICEDETAIL, ya
que tanto en la definicin de Sum como Count, hemos referenciado a un nico atributo asociado a INVOICEDETAIL.
Cuando definimos una frmula Aggregate, ya tenemos conocimiento de qu tabla pretendemos navegar para efectuar el
clculo. Los atibutos que podremos referenciar en la definicin de una frmula Aggregate debern pertenecer a la tabla a
ser navegada y su tabla extendida + a la tabla asociada al atributo que se est definiendo como frmula y su tabla
extendida. De involucrar en una frmula Aggregate atributos que no pertenezcan a este contexto mencionado, un error se
reportar en el listado de navegacin correspondiente.
Por ltimo, de haber atributos en comn (de igual nombre) en las tablas involucradas en la definicin de una frmula,
GeneXus aplicar esa relacin (es decir, filtrar automaticamente por igualdad por los atributos de igual nombre). Esto es lo
que sucede en estos 2 ejemplos, que GeneXus cuenta y suma las lneas relacionadas a sus cabezales (al sumar y contar,
aplica automticamente el filtro INVOICEDETAIL.InvoiceId = INVOICE.InvoiceId ).
104
105
Frmulas
Clasificacin
Ejemplos de Frmulas Aggregate (Globales) :
Invoice
Product
{
{
InvoiceId*
ProductId*
CustomerId
ProductDescription
CustomerName
PriceList
InvoiceDate
{
InvoiceDetails Count(InvoiceDetailQuantity)
ProductPriceListDate*
InvoiceAmount Sum(InvoiceDetailAmount)
ProductPriceListPrice
Detail
}
{
}
InvoiceDetailId*
ProductId
ProductDescription
InvoiceDetailQuantity
Max(ProductPriceListDate,
InvoiceDetailProductPrice
ProductPriceListDate<=InvoiceDate,
InvoiceDetailAmount
0, ProductPriceListPrice)
}
}
InvoiceDetailProductPrice*InvoiceDetailQuantity
Hemos modificado el diseo de las transacciones para que en lugar de representar que cada
producto tiene un nico precio, representamos que cada producto tiene una lista de precios de
acuerdo a la fecha de cambio de los mismos.
Al efectuar este cambio, el atributo ProductPriceListPrice no podr estar presente en el
segundo nivel de la transaccin Invoice. Por qu? Porque el nuevo diseo estar
representando que un producto ya no tendr solamente un precio, sino muchos: uno por cada
fecha de cambio de precio del mismo. Por lo tanto, para un producto en una lnea de una
factura, tendremos que buscar el precio vigente del mismo, teniendo en cuenta la fecha de la
factura.
Recordemos que los atributos que se pueden inferir en determinado nivel de una transaccin,
son los que pertenecen a la tabla extendida de la tabla base asociada al nivel en cuestin. En
este ejemplo, la tabla extendida de la tabla INVOICEDETAIL, no incluye a la tabla
PRODUCTPRICELIST (en la cual se encuentra el atributo ProductPriceListPrice):
106
Valor de retorno si no se
encuentra ningn registro
que cumpla con las
condiciones
Atributo a maximizar de
entre los registros que
cumplan las condiciones
Para el registro
encontrado, se retorna
este atributo
GeneXus inferir la tabla a ser navegada por el ltimo parmetro de la frmula (el atributo de
retorno).
Como ya se ha explicado, los atibutos que podremos referenciar en la definicin de una frmula
Aggregate debern pertenecer a la tabla a ser navegada y su tabla extendida + a la tabla
asociada al atributo que se est definiendo como frmula y su tabla extendida. De involucrar
atributos que no pertenezcan a este contexto mencionado, un error se reportar en el listado de
navegacin correspondiente.
GeneXus considerar al momento de efectuar la bsqueda, la condicin explcita de filtro + las
condiciones mplicitas detactadas.
La frmula Min es totalmente anloga a Max, con la nica diferencia de que al encontrar un conjunto
de registros que cumplan con las condiciones, se seleccionar aquel registro que tenga valor
mnimo para el atributo indicado en el primer parmetro y se retornar el valor de retorno que se
haya indicado en el ltimo parmetro.
La frmula Find por su parte, tambin permite buscar un registro que cumpla con ciertas
condiciones, sin embargo de haber ms de 1 registro que cumpla con ellas, la frmula devolver el
atributo de retorno correspondiente al primer registro encontrado (sin maximizar ni minimizar un
valor en el conjunto de registros que cumplan con las condiciones). La sintaxis Find es:
Find (Expresin de retorno, [Condicin explcita], [Valor por defecto]) [if Condicin de
disparo]
107
Frmulas
Clasificacin
Ejemplo de Frmula Compuesta (Global):
Customer
{ CustomerId*
CustomerName
CustomerTotalPurchases
CustomerTotalPayments
CustomerBalance
CustomerAverage
}
Sum(InvoiceAmount) / Count(InvoiceAmount)
108
Comunicacin
entre objetos
109
Procedimiento
Transaccin
Web Panel
Procedimiento PDF
Los objetos GeneXus pueden comunicarse entre ellos o con otros programas externos.
Un objeto GeneXus puede llamar o ser llamado por otro objeto, intercambiando informacin a travs
de parmetros.
Veremos a continuacin cmo invocar desde un objeto a otro, y cmo especificar los parmetros (en
el objeto llamador y en el llamado) para el intercambio de la informacin.
El esquema presentado arriba ilustra las posibles interacciones entre objetos GeneXus para una
aplicacin Web. Obsrvese que la flecha simple entre Web Panel y Procedimiento PDF (as como
entre Transaccin y Procedimiento PDF) indica que un Web Panel podr invocar a un Procedimiento
PDF pero un Procedimiento PDF no podr invocar a un Web Panel (o transaccin Web).
110
/*Invocacin a PgmName*/
/*Declaracin de parmetros
en el objeto invocado*/
puede omitirse
2)
/*Declaracin de
parmetros
en el objeto invocado*/
CALL - Permite invocar a un objeto GeneXus o a un programa externo, tanto sin pasarle
parmetros, como pasndole.
UDP (User Defined Procedure) - Permite invocar a un objeto GeneXus o programa externo tanto
sin pasarle parmetros como pasndole, y con la particularidad de que el programa llamado
retornar necesariamente al menos un valor al programa que lo invoc. En ambientes Web, un
objeto con interfaz una vez invocado no devuelve el control al llamdor, por lo que UDP se utiliza
nicamente para invocar a Procedimientos y Data Providers (debido a que estos cumplen la
condicin de ejecutar y devolver el control al llamador).
Una invocacin (ya sea con CALL o UDP) podr escribirse en distintas partes del objeto llamador,
dependiendo de si el mismo es una transaccin, web panel, procedimiento, etc.
A su vez UDP puede utilizarse tambin en la definicin de un atributo frmula. Es decir, se define que
cierto atributo es una frmula y que la definicin de la misma consiste en la invocacin a un
procedimiento utilizando UDP.
Cuando en la sintaxis de la invocacin se escribe el nombre del objeto invocado y ningn mtodo de
invocacin, se asume que se est invocando con udp, por lo que puede omitirse y escribirse
directamente:
att|&var = PgmName( par1, ..., parN)
PARM Cuando un objeto es invocado desde otro con parmetros, debe tener declarada la lista de
parmetros que recibe. Esta declaracin se realiza mediante la regla: PARM.
A continuacin daremos ms detalles acerca del uso de CALL, UDP y PARM.
111
2)Ej:
Parm(InvoiceId)
&discount = GetDiscount.udp(ProductId,CustomerId)
En el proc GetDiscount
Parm(ProductId,CustomerId , &disc);
Aqu mostramos un ejemplo de uso de CALL para realizar una invocacin y otro ejemplo de uso de
UDP.
Dependiendo de qu objeto llamador se trate, estas invocaciones podrn escribirse en una seccin u
otra del mismo, pero independientemente de eso, aqu apuntamos a mostrar que CALL permite
invocar a un objeto con estilo de invocacin a un programa, mientras que UDP invoca a un objeto con
estilo de invocacin a una funcin.
En el primer ejemplo se est utilizando CALL para invocar a un procedimiento pdf (objeto ListInvoice)
pasndole un parmetro (InvoiceId). En el procedimiento invocado se ha declarado el parmetro que
recibe (en su seccin de reglas, mediante la regla parm).
En el segundo ejemplo se est utilizando UDP para invocar a un procedimiento (objeto GetDiscount)
pasndole dos parmetros (ProductId, CustomerId). Ahora, observemos en la sintaxis de la
invocacin al procedimiento, que el mismo retorna un valor (en la variable &disc). Por este motivo, en
el procedimiento invocado se han declarado tres parmetros utilizando la regla parm: los dos
parmetros recibidos + el parmetro de retorno en ltimo lugar.
Podemos ver entonces que cuando se utiliza CALL para invocar a un objeto envindole N
parmetros, se deben declarar los N parmetros (posicionales y del mismo tipo de datos que los
enviados) en el objeto invocado mediante la regla parm.
En cambio cuando se utiliza UDP para invocar a un objeto envindole N parmetros (a menos que se
trate del caso particular de un Data Provider, caso que veremos ms adelante):
en la regla parm del objeto invocado se deben declarar N + 1.
El ltimo parmetro declarado en la regla parm del objeto invocado corresponde al que se encuentra
al principio de todo en la invocacin, es decir, al que recibe el valor retornado.
En algn lugar del objeto invocado se le deber asignar valor al parmetro de retorno.
112
Al definir una invocacin a un objeto (ya sea utilizando CALL o UDP), si se tienen que enviar datos
por parmetro al objeto invocado, resulta evidente determinar si enviar atributos y/o variables: si un
dato a ser enviado por parmetro, se encuentra en el objeto invocador, en un atributo, habr que
enviar el mismo; y si se encuentra en una variable, habr que enviar la variable.
Sin embargo, al declarar la lista de parmetros en el objeto invocado, el programador GeneXus
deber decidir para cada parmetro, si declararlo mediante un atributo o una variable,
independientemente de cmo haya sido enviado.
Cul es la diferencia entre declarar un parmetro como variable o como atributo en la regla parm
del objeto invocado? Si se declara una variable, se la podr utilizar libremente en la lgica del objeto
invocado: se la podr utilizar como condicin de filtro por igualdad, por mayor, mayor o igual, menor,
menor o igual, LIKE, etc.; se la podr utilizar para alguna operacin aritmtica, como bandera, o lo
que se necesite. Si en cambio se declara un atributo, automticamente el mismo actuar como filtro
por igualdad en el objeto, no siendo posible modificar el valor recibido.
Cuando lleguemos a la etapa del curso en la cual podamos invocar a procedimientos pdf para
listados, pasndoles parmetros, as como a otros objetos, podremos terminar de comprender mejor
este tema.
113
Ejemplo:parm(out:&par1,in:&par2,&par3,inout:&par4);
Ventajas:
Mejor especificacin delasemntica delas interfaces.
Independenciadellenguajedegeneracin.
Optimizar el pasaje de parmetros de las aplicaciones de acuerdo a la
arquitectura en la que stas se implementan (ventaja contrapuesta a la
anterior).
Como se puede percibir claramente en la sintaxis del ejemplo, el primer parmetro definido es de salida, el
segundo parmetro es de entrada, y el cuarto parmetro es de entrada-salida. Cuando no se especifica
nada, como es el caso del tercer parmetro de la sintaxis, depender de lo siguiente:
si el objeto fue invocado con CALL, el parmetro, ser de entrada-salida.
si el objeto fue invocado con UDP, y se trata del ltimo parmetro, ser de salida; y si se trata de otro
parmetro distinto del ltimo, depender del lenguaje de generacin.
Declarar explcitamente cmo se desea que cada parmetro opere, tiene las siguientes ventajas:
1. Mejor especificacin de la semntica de las interfaces; es decir, tanto para GeneXus como para el
programador cuando trabaje con un objeto, ser claro:
- si el mismo vendr con valor y luego de la ejecucin del objeto invocado, se
devolver al objeto invocador el valor con que haya quedado (inout).
- si el mismo vendr con valor y luego de la ejecucin del objeto invocado, no se
devolver al objeto invocador el valor con que haya quedado (in).
- si el mismo no vendr con valor y luego de la ejecucin del objeto invocado, se devolver
al objeto invocador el valor que tenga (out).
2. Independencia del lenguaje de generacin; es decir, si se define explcitamente cmo se desea que cada
parmetro opere, al generar las aplicaciones utilizando diferentes lenguajes de generacin no estar
cambiando el comportamiento de los parmetros en base al comportamiento por defecto del lenguaje de
generacin correspondiente.
3. Optimizar el pasaje de parmetros de acuerdo a la arquitectura en la que stas se generen (siendo una
ventaja contrapuesta a la anterior); esto se refiere a lo siguiente: para la mayora de los lenguajes es ms
eficiente pasar los parmetros por referencia (inout) que por valor (in / out); pero en Java, por ejemplo, los
parmetros solo se pueden pasar por valor, por lo que para lograr la funcionalidad de pasarlos por referencia
es necesario hacer conversiones de parmetros, lo cual puede redundar en un overhead importante; por otro
lado, cuando se trata de aplicaciones distribuidas (por ejemplo Java con RMI o HTTP), la utilizacin de
parmetros de tipo out tiene la ventaja de que no es necesario enviar al parmetro en la invocacin, a
diferencia de si los parmetros se definen de inout (que implica que haya que pasar todos los parmetros);
esto tiene como consecuencia que se enven ms bytes de los necesarios, lo cual es inconveniente
especialmente en entornos tales como Internet.
114
1)
2)
control.Link = Link(URL)
Ej: imagen.Link = Link(http://www.artech.com.uy)
La funcin Link se asocia a la propiedad link de un control dentro de cualquier evento de una
transaccin o web panel, teniendo como resultado que al hacer clic sobre dicho control se realizar la
llamada al objeto o URL referenciada en el link.
PgmName (el objeto invocado) podr ser un web panel, transaccin, o procedimiento PDF1.
--------------------------------------------------------------------------------------------------------------------------------Tambin un procedimiento HTTP, pero no profundizaremos sobre este concepto en este curso
115
1)
PgmName.Link([,par1 , parN])
Ej: Customer.Link(CustomerId)
2)
Link(URL)
Ej: Link(http://www.google.com)
El comando Link puede ser utilizado dentro de cualquier evento de una transaccin o web panel1.
Cuando se ejecute el evento, al llegar a la sentencia con el comando Link, se redireccionar en
forma automtica a la URL especificada.
En caso de utilizarse el comando Link como en el ejemplo 1, invocando a un PgmName (siendo
PgmName un web panel, transaccin o procedimiento PDF), ser equivalente a la utilizacin de Call.
Opcionalmente se podrn pasar parmetros al objeto invocado, debiendo declararse los mismos en el
objeto llamado, con la regla parm.
-------------------------------------------------------------------------------------------------------------------------------1 Tambin un procedimiento HTTP, pero no profundizaremos sobre este concepto en este curso.
116
Orden de ejecucin de
reglas y frmulas
117
Orden de ejecucin de
reglas y frmulas
Transaccin "Invoice"
InvoiceId*
InvoiceDate
CustomerId
CustomerTotalPurchases
CategoryDiscount
InvoiceDiscount
= InvoiceSubTotal *CategoryDiscount
InvoiceShippingCharge = Max( ShippingDate, ShippingDate
<=InvoiceDate,,ShippingCharge)
InvoiceSubTotal
= SUM( InvoiceDetailAmount )
InvoiceTotal
= InvoiceSubTotal InvoiceDiscount
+ InvoiceShippingCharge
(ProductId*
ProductPrice
ProductStock
InvoiceDetailQuantity
InvoiceDetailAmount) = InvoiceDetailQuantity *
ProductPrice
Reglas:
Customer
CustomerId*
CustomerName
CategoryId
CustomerTotalPurchases
Category
CategoryId*
CategoryDiscount
Shipping
ShippingDate*
ShippingCharge
Product
ProductId*
ProductPrice
ProducStock
La forma de programar el comportamiento de las transacciones es definiendo reglas, las cuales se escriben de
forma declarativa. A su vez si hay clculos para efectuar, se puede optar por la alternativa de definir atributos
frmula.
El programador GeneXus en ningn momento especifica la secuencia de ejecucin de las reglas y frmulas
definidas en una transaccin, sin embargo al momento de generar, GeneXus determina las dependencias
existentes entre las reglas y frmulas definidas.
Supongamos que estamos definiendo una aplicacin para una empresa que vende determinados productos, y
que cuenta con un servicio de entrega a domicilio que lleva la mercadera a sus clientes. Y definimos entre
otras, las siguientes 5 transacciones:
"Customer" (para registrar los clientes de la empresa)
Category (a las que pertenece cada cliente)
Shipping (envos: guarda un histrico de costos de envo)
"Invoice" (facturas que se emiten a los clientes)
"Product" (productos vendidos por la empresa)
Se resalta la estructura de la transaccin "Invoice", con sus atributos frmulas y sus reglas declaradas.
En qu orden se dispararn las reglas y frmulas de la transaccin "Invoice"?
118
rbol de evaluacin
R. Add(InvoiceTotal, CustomerTotalPurchases);
F. InvoiceTotal = InvoiceSubTotal - InvoiceDiscount +
InvoiceShippingCharge
F. InvoiceDiscount = InvoiceSubTotal*CategoryDiscount
F. InvoiceShippingCharge = MAX( ShippingDate, ShippingDate <=
InvoiceDate,,ShippingCharge)
F. InvoiceSubTotal = SUM( InvoiceDetailAmount )
F. InvoiceDetailAmount = InvoiceDetailQuantity *ProductPrice
R. Subtract(InvoiceDetailQuantity, ProductStock) ;
R. Error( Insuffcient Stock) if ProductStock < 0 ;
CustomerTotalPurchases
InvoiceTotal
InvoiceDiscount
InvoiceShippingCharge
error (Insufficient Stock )
ProductStock
InvoiceSubTotal
InvoiceDetailAmount
InvoiceDetailQuantity
ShippingDate
CategoryDiscount
InvoiceDate
ShippingCharge
ProductPrice
Al momento de generar el programa asociado a la transaccin "Invoice", GeneXus extraer las dependencias
existentes entre las reglas y frmulas definidas; construir lgicamente un rbol de dependencias (o rbol de
evaluacin) que determinar la secuencia de evaluacin.
Podemos imaginar que el rbol se ejecuta de abajo hacia arriba, es decir que cada vez que cambia el valor de
un atributo, se ejecutan todas las reglas y frmulas que dependen de ese atributo (y que en el rbol se
encuentran hacia arriba).
Por ejemplo, si cambia la cantidad de una lnea de una factura (InvoiceDetailQuantity), como este atributo
interviene en la frmula que calcula el importe de la lnea (InvoiceDetailAmount), dicha frmula se redisparar.
Por cambiar el importe de una lnea, deber redispararse la frmula correspondiente al subtotal de la factura
(InvoiceSubTotal) y en consecuencia, tambin deber recalcularse la frmula correspondiente al descuento
(InvoiceDiscount), ya que depende del subtotal. Deber redispararse tambin la frmula correspondiente al
total de la factura (InvoiceTotal) ya que depende tanto del valor de InvoiceSubTotal como del valor de
InvoiceDiscount. Por ltimo, por cambiar el total tambin se tendr que disparar la regla Add(InvoiceTotal,
CustomerTotalPurchases);.
Adems de dispararse todas las frmulas y reglas involucradas en la rama derecha del rbol desde el atributo
InvoiceDetailQuantity, tambin se dispararn las frmulas y reglas involucradas en la rama izquierda. Es decir,
que al cambiar el valor del atributo InvoiceDetailQuantity, se
redisparar tambin la regla
Subtract(InvoiceDetailQuantity, ProductStock); y en consecuencia, por modificar esta regla el valor del atributo
ProductStock, se evaluar si habr que disparar la regla Error(Stock Insuficiente) if ProductStock < 0;
Concluyendo, las reglas y frmulas que se definen en una transaccin suelen estar interrelacionadas y
GeneXus determina las dependencias entre ellas as como su orden de evaluacin.
119
Estas reglas estn interrelacionadas porque las dos involucran al atributo ProductStock. Ahora, mientras la
segunda solamente consulta su valor, la primera lo actualiza. Entonces, la regla que actualiza al atributo ser la
que se disparar primero, y luego se disparar la que lo consulta.
Toda regla que actualice el valor de un atributo se disparar antes que una regla que lo consulte (esto se puede
observar claramente en el rbol). Por este motivo es que la regla Error consulta si el atributo ProductStock qued
con valor negativo; porque como dijimos la sustraccin se realizar primero.
En la programacin clsica se suele consultar primero si alcanza el stock, y en caso de que sea suficiente recin
se hace la sustraccin. Por eso quienes estn aprendiendo GeneXus pueden intuitivamente escribir la regla:
Error(Insufficient Stock') if InvoiceDetailQuantity > ProductStock. Esta sintaxis es correcta, sin embargo no es
correcta su lgica ya que como venimos explicando, en el rbol de evaluacin determinado por GeneXus primero
se disparar la regla Subtract y luego la regla Error; por lo tanto tendremos que especificar que se dispare el
mensaje de error si es que qued el stock con valor negativo, dado que ya se habr ejecutado la sustraccin al
momento de consultar el valor de ProductStock.
As que la regla que se debe definir es:
Error(Insufficient Stock) if ProductStock < 0;
Y no:
Error('Insufficient Stock') if InvoiceDetailQuantity > ProductStock;
Cuando se dispara una regla Error, se detiene cualquier actualizacin a la base de datos y se desarma el
rbol de evaluacin, quedando todo en el estado anterior a producirse el error. Siguiendo el ejemplo que
venamos viendo, si al dispararse la regla Subtract el stock quedara negativo, se disparara la regla Error. Como
consecuencia de dispararse la regla Error, se deshara el Subtract que se haba ejecutado, as como todas las
dems reglas y frmulas que se hayan ejecutado (reclculo de los atributos InvoiceDetailAmount,
InvoiceSubTotal, ...., CustomerTotalPurchases).
120
Total
Calculado
Total
Ingresado
SupplierId*
InvoiceId*
...
InvoiceEntTotal
Entered Total
InvoiceDetailAmount
( ProductId*
InvoiceDetailQuantity
InvoiceDetailPrice
InvoiceDetailAmount = InvoiceDetailPrice * InvoiceDetailQuantity)
...
InvoiceCalcTotal = SUM(InvoiceDetailAmount) Calculated Total
En la mayora de los casos el orden de ejecucin de las reglas definido por GeneXus a partir de nuestras
especificaciones es el deseado. Pero en algunos casos podemos querer cambiar el momento de disparo de
una regla.
Ejemplo:
Definimos una transaccin para registrar las facturas que nos entregan nuestros proveedores.
El identificador del primer nivel es compuesto por el identificador de proveedor y el identificador de factura, ya
que el nmero de factura no nos sirve como identificador nico, porque proveedores distintos pueden repetir el
mismo nmero de factura.
Para cada factura de un proveedor que se ingrese, nos interesa controlar que el total que venga escrito en la
factura (y que se ingresar en el atributo InvoiceEntTotal) sea correcto. Para hacer este control, definimos al
atributo InvoiceCalcTotal como frmula vertical SUM(InvoiceDetailAmount), y agregamos una regla Error que
se disparar si no coinciden los valores de los atributos InvoiceEntTotal y InvoiceCalcTotal:
Error('El total ingresado no coincide con el total calculado') if InvoiceCalcTotal <> InvoiceEntTotal;
Si construimos el rbol de evaluacin correspondiente a las frmulas y regla que hemos definido en esta
transaccin:
121
vemos que las dependencias indican que cada vez que se agreguen, modifiquen o eliminen valores de los
atributos InvoiceDetailPrice e InvoiceDetailQuantity en las lneas, se recalcular el valor del atributo
InvoiceDetailAmount correspondiente; en consecuencia, se recalcular el valor del atributo frmula
InvoiceCalcTotal que hemos definido para tener el total calculado de la factura; y como este atributo est
involucrado en la condicin de disparo de la regla Error, si se cumple dicha condicin de disparo, se disparar la
regla Error(El total ingresado no coincide con el total calculado) if InvoiceCalcTotal <> InvoiceEntTotal.
Ahora, prestemos atencin a que la condicin de disparo InvoiceCalcTotal <> InvoiceEntTotal se va a cumplir
repetidamente en la medida que el operador vaya ingresando lneas, porque para cada lnea que se ingrese se
calcular el valor del atributo frmula InvoiceDetailAmount de la lnea, y en consecuencia se recalcular el valor
del atributo frmula InvoiceCalcTotal. Pero el valor calculado de este atributo no coincidir con el valor ingresado
en el atributo InvoiceEntTotal hasta que no se hayan ingresado todas las lneas de la factura; entonces, se
disparar la regla Error(The calculated total doesnt match with the entered total) if InvoiceCalcTotal <>
InvoiceEntTotal;.
Concluimos entonces que en este caso no nos sirve lo que determina el rbol de evaluacin, ya que no queremos
que se evale la condicin de disparo de la regla Error cada vez que el operador ingrese, modifique o elimine
lneas, sino que recin necesitamos que se evale cuando el usuario haya terminado de trabajar con todas las
lneas de la factura.
GeneXus ofrece eventos o momentos de disparo en las transacciones, que ocurren antes o despus de
determinada accin, como la grabacin del cabezal, o de una lnea. Las reglas de las transacciones pueden
condicionarse de manera tal de dispararse en el preciso instante en que ocurre alguno de esos eventos de
disparo.
Siguiendo el ejemplo que venamos viendo, existe un evento de disparo que ocurre luego de iterar en un nivel y
salir del mismo. La sintaxis de este evento de disparo es: AfterLevel Level Atributo, debiendo ser Atributo un
atributo perteneciente al nivel que se ha iterado y se abandona.
De modo que a la regla Error de nuestro ejemplo, le agregaramos este evento de disparo, y quedara definida de
la siguiente forma:
Error(The calculated total doesnt match with the entered total) if InvoiceCalcTotal<>InvoiceEntTotal On
AfterLevel Level ProductId.
Con este evento de disparo que hemos agregado a la regla logramos controlar lo que desebamos en el
momento adecuado.
Adems de este evento de disparo, existen otros que veremos a continuacin.
122
Eventos de disparo
La mayora de las reglas de transacciones permiten que se les
agregue de ser necesario un evento o momento de disparo.
Al agregar un evento o momento de disparo a una regla,
estaremos especificando que la regla se deber ejecutar en ese
determinado momento.
Eventos de disparo:
BeforeValidate
AfterValidate
BeforeInsert, BeforeUpdate, BeforeDelete
AfterInsert, AfterUpdate, AfterDelete
AfterLevel
BeforeComplete
AfterComplete
Al momento de la confirmacin de la transaccin, ocurre una serie de acciones que es necesario conocer para poder
programar correctamente el comportamiento de las reglas.
Para una transaccin de dos niveles, podramos enumerarlas como sigue:
validacin de los datos del cabezal
grabacin fsica del cabezal (ya sea insercin, modificacin o eliminacin)
validacin de los datos de la primera lnea
grabacin fsica de los datos de la primera lnea
validacin de los datos de la segunda lnea
grabacin fsica de los datos de la segunda lnea
123
Los eventos de disparo de reglas permiten definir que se ejecuten antes o despus de alguna de las acciones que
acabamos de enumerar. Veremos cundo ocurre cada evento de disparo.
Evento de disparo: BeforeValidate
Este evento de disparo ocurre un instante de tiempo antes de que la informacin de la instancia con la que se est
trabajando (cabezal o lnea x) sea validada (o confirmada). Es decir, ocurrir un instante de tiempo antes de la accin
de validacin del cabezal o validacin de la lnea, segn corresponda. Observar que aqu tambin se habrn
disparado todas las reglas segn el rbol de evaluacin que no estn condicionadas a evento de disparo alguno.
Eventos de disparo: AfterValidate, BeforeInsert, BeforeUdate, BeforeDelete
El evento de disparo AfterValidate permite especificar que una regla se ejecute inmediatamente antes de que se
grabe fsicamente cada instancia del nivel al cual est asociada la regla, en la tabla fsica correspondiente, y despus
de que se hayan validado los datos de esa instancia.
En otras palabras, si se le agrega el evento de disparo AfterValidate a una regla, la misma se ejecutar para cada
instancia del nivel al cual est asociada, inmediatamente antes de que la instancia se grabe fsicamente (ya sea
que se inserte, modifique o elimine) como registro en la tabla fsica asociada al nivel.
EJEMPLOS
1. Hay veces en las que no contamos con la posibilidad de utilizar la propiedad Autonumber para numerar de forma
automtica y correlativa los atributos que son clave primaria simple. Tal funcionalidad es provista por los manejadores
de base de datos (DBMSs) y GeneXus la aprovecha y permite usarla; sin embargo en los casos en los que no se
trabaja con un manejador de base de datos, no contamos con la posibilidad de utilizar esta facilidad.
En esos casos en los que necesitamos numerar de forma automtica y correlativa ciertos atributos, y no podemos
utilizar la propiedad Autonumber, debemos resolverlo programndolo. Para ello solemos definir una transaccin
conteniendo dos atributos, uno para almacenar un literal y otro para almacenar el ltimo nmero asignado
automticamente al atributo descripto por el literal; la transaccin conlleva la creacin de una tabla, y definimos un
procedimiento que consulta esa tabla, obtiene el ltimo nmero asignado para el atributo a ser numerado, le suma uno
y devuelve el prximo nmero, adems de actualizarlo en la tabla.
Para invocar al procedimiento de numeracin automtica se debe definir en las transacciones que lo requieran una
regla del siguiente estilo:
CustomerId = PGetNumber.udp( CUSTOMER ) if Insert on AfterValidate;
En este caso se est queriendo autonumerar el atributo CustomerId de la transaccin Customer
Del mismo modo, si queremos autonumerar el identificador de facturas, escribiramos en la transaccin Inovice la
siguiente regla:
InvoiceId = PGetNumber.udp( INVOICE ) if Insert on AfterValidate;
De esta forma definimos que se efecten numeraciones automticas en las transacciones nicamente cuando se
realicen inserciones (por la condicin de disparo: if Insert) e inmediatamente antes de que se grabe fsicamente
cada instancia a ser insertada (por el evento de disparo: on AfterValidate) a travs del primer nivel de la transaccin
(porque en las dos reglas de invocacin mostradas, hay solamente un atributo involucrado que pertenece al primer
nivel de las transacciones "Customer" e "Invoice" respectivamente).
El motivo por el cual agregamos el evento de disparo on AfterValidate a estas reglas es para invocar al procedimiento
de numeracin automtica inmediatamente antes de que se inserte el registro en la base de datos y luego de la
validacin, intentando de esta forma tener el mayor grado de seguridad posible de que el nmero asignado ser
utilizado (y no perder nmeros). Piense unos instantes el lector cundo se disparara la regla anterior de no estar
condicionada a evento de disparo alguno, y qu podra pasar en el caso de que fallara la validacin de alguno de los
datos del cabezal. La respuesta es simple: se perdera un nmero. Es decir, si el nmero de factura anterior fuera 5 y
el usuario quisiera ingresar la siguiente factura, la regla de asignacin con udp que invoca la procedimiento de
numeracin se disparara ni bien se ingresara a la transaccin estando en modo insert, ya que involucra al primer
atributo del cabezal. El procedimiento devolvera el nmero 6, y si validando los datos del cabezal se encuentra algn
error que no permite continuar con el proceso, y se abandonara la transaccin, por ejemplo, ese nmero 6 se habr
perdido y la prxima factura, que correlativamente debera tener el nmero 6 no lo tendr, tendr el 7.
124
Existen tres eventos de disparo que ocurren en el mismo momento que el AfterValidate, pero que ya contienen
intrnseco el modo. Ellos son: BeforeInsert, BeforeUpdate y BeforeDelete..
Es equivalente escribir la regla presentada antes como lo hicimos, a escribirla:
InvoiceId = PGetNumber.udp( INVOICE ) on BeforeInsert;
Observar que aqu es redundante condicionar la regla a If Insert. Por tanto, valen las siguientes equivalencias:
on BeforeInsert If Insert on AfterValidate
on BeforeUpdate If Update on AfterValidate
on BeforeDelete If Delete on AfterValidate
tiempo
Si hacemos un esquema de las acciones que rodean al evento de disparo, quedarn claros los dos sinnimos elegidos
para este evento (AfterValidate y BeforeInsert para modo insert)
VALIDACIN DE LOS DATOS
AfterValidate BeforeInsert BeforeUpdate BeforeDelete
GRABACIN DEL REGISTRO (insert, update, delete segn corresponda)
2) Si definimos una regla a la cual le incluimos tambin el evento de disparo on AfterValidate, u on BeforeInsert,
BeforeDelete, BeforeUdate pero a diferencia de los ejemplos recin vistos, se referencia en la regla al menos un
atributo del segundo nivel de la transaccin en la cual se est definiendo la regla, la misma estar asociada al
segundo nivel1. Por lo tanto, la regla se ejecutar inmediatamente antes de que se grabe fsicamente cada
instancia correspondiente al segundo nivel de la transaccin.
---------------------------------------------------------------------------------------------------------------------------------------------------1 Existe otra forma de provocar que una regla que contiene atributos de un nivel determinado, se dispare en el nivel
siguiente, mediante la clusula Level que mencionamos cuando vimos conceptos importantes sobre reglas de
transacciones.
125
126
tiempo
Ampliamos el esquema que habamos efectuado antes, de las acciones que rodean a los eventos de disparo vistos
hasta ahora:
VALIDACIN DE LOS DATOS
AfterValidate BeforeInsert BeforeUpdate BeforeDelete
GRABACIN DEL REGISTRO (insert, update, delete segn corresponda)
AfterInsert AfterUpdate AfterDelete
Este esquema se repite para cada instancia del nivel. Por ejemplo, pensemos en el ingreso de las lneas de una factura.
Para cada lnea ocurrir este esquema, por lo que podemos pensar en un loop que se repite hasta que se termina de
grabar la ltima lnea.
La accin que sucede a la grabacin de la ltima lnea sera el abandonar ese nivel (en este caso el de las lneas de
factura). Y luego de esa accin, a menos que venga otro nivel con el que se volvera a ingresar en el esquema anterior,
ocurrir la ltima accin en la ejecucin, que es el commit.
Entre la accin de abandonar el nivel, y el commit tendremos un evento (que admite dos nombres distintos) y otro para
luego del commit. Son los que veremos a continuacin pero que ya mostramos en esquema:
tiempo
loop
ABANDONAR NIVEL 2
AfterLevel - BeforeComplete
COMMIT
AfterComplete
127
El evento de nombre BeforeComplete, en este caso, coincide con el AfterLevel. Si observamos el esquema
presentado en la pgina anterior, podemos ver que el instante de tiempo que hay entre que se abandona el ltimo nivel
y se realiza el commit es el instante en que ocurren estos eventos. Son dos nombres para referirnos a lo mismo.
Cuidado que esto es as siempre y cuando el nivel abandonado sea el ltimo. Supngase por ejemplo una transaccin
con dos niveles paralelos. Por ejemplo, si agregamos al cliente sus direcciones de mail y sus nmeros telefnicos
(puede tener varios):
{CustomerId*
CustomerName
{CustomerPhone*
}
{CustomerEMail*
}
}
El momento en que deber dispararse una regla condicionada a: On AfterLevel Level CustomerPhone NO
COINCIDIRA con el de una regla condicionada a on BeforeComplete.Mientras que la primera se disparar cuando se
abandona el nivel de los telfonos, y antes de entrar a validar todos los emails, la segunda se disparar despus de
abandonar este ltimo nivel.
En este caso el evento BeforeComplete coincidir con el AfterLevel Level CustomerEMail.
Evento de disparo: AfterComplete
Este evento corresponde al instante de tiempo que sucede al commit. Hablaremos ms de este evento unas pginas
adelante, cuando estudiemos la integridad transaccional.
Si se abre la transaccin de facturas, se ingresan 3 facturas (cabezal y sus respectivas lneas) y se cierra la transaccin,
ocurrirn 3 commits (uno al final de cada ingreso de cabezal + lneas) y 3 eventos AfterComplete.
128
REGLAS STAND-ALONE
EVALUACION DE REGLAS Y
FORMULAS SEGN ARBOL
El siguiente ejemplo pretende mostrar visualmente en qu momentos se irn disparando las reglas y frmulas
definidas en una transaccin.
El disparo de reglas y frmulas se ir haciendo de acuerdo al rbol de evaluacin, siguiendo el orden que ste
determina.
129
REGLAS STAND-ALONE
EVALUACION REGLAS Y FRMULAS SEGN ARBOL
BeforeValidate
VALIDACIN
AfterValidate / BeforeInsert / Update / Delete
GRABACION DEL CABEZAL
AfterInsert / Update / Delete
EVALUACION DE REGLAS Y
FORMULAS SEGN ARBOL
PARA CADA
LINEA
BeforeValidate
VALIDACIN
AfterValidate / BeforeInsert / Udpate / Delete
GRABACION DE LA LINEA
AfterInsert/Update/Delete
ABANDONAR NIVEL 2
AfterLevel Level attNivel2 - BeforeComplete
COMMIT
AfterComplete
&A = parmetro2;
&A = 7;
Por lo tanto, son las primeras reglas que pueden ejecutarse.
Luego de la ejecucin de las reglas stand alone, se ejecutan las reglas asociadas al primer nivel de la
transaccin, que no tengan evento de disparo definido, siguiendo el orden de dependencias determinado
por GeneXus (as como las frmulas asociadas al primer nivel). A modo de ejemplo, se disparar la regla:
Default( InvoiceDate, &Today);
Despus de ejecutadas las reglas mencionadas para el cabezal, se ejecutarn todas las reglas que tengan
como evento de disparo BeforeValidate, ya que inmediatamente despus ocurrir la accin de validacin
(o confirmacin) de la informacin de ese primer nivel.
Inmediatamente despus de la validacin del primer nivel se ejecutan las reglas asociadas al primer nivel de
la transaccin que incluyan en su definicin el evento de disparo AfterValidate, o los BeforeInsert,
BeforeUpdate, BeforeDelete, dependiendo del modo en el que se est.
Por ejemplo: Si no podemos autonumerar las facturas con la propiedad Autonumber por no ser soportada
por el DBMS elegido:
InvoiceId = PGetNumber.udp(INVOICE) on BeforeInsert;
130
Seguidamente a la ejecucin de las reglas asociadas al primer nivel con alguno de estos eventos de disparo se
ejecuta la accin de grabacin; es decir, se grabar fsicamente la instancia correspondiente al primer nivel de
la transaccin como registro fsico en la tabla correspondiente (en este ejemplo, en la tabla: INVOICE).
Inmediatamente despus de haberse grabado esa instancia:
si la grabacin correspondi a una insercin: se ejecutarn las reglas asociadas al primer nivel de la
transaccin con evento de disparo AfterInsert.
si la grabacin correspondi a una actualizacin: se ejecutarn las reglas asociadas al primer nivel de la
transaccin con evento de disparo AfterUpdate.
si la grabacin correspondi a una eliminacin: se ejecutarn las reglas asociadas al primer nivel de la
transaccin con evento de disparo AfterDelete.
Si se trata de una transaccin de dos niveles, como en este caso, a continuacin se ejecutar para
cada una de las lneas:
En primer lugar, las reglas asociadas al segundo nivel de la transaccin que no tengan evento de
disparo definido, siguiendo el orden de dependencias determinado por GeneXus (as como las
frmulas asociadas al segundo nivel). Ejemplos de ello son la regla
Subtract( InvoiceDetailQuantity, ProductStock );
la frmula
InvoiceDetailAmount = InvoiceDetailQuantity*ProductPrice.
Despus de ejecutadas las reglas mencionadas para una lnea, se ejecutarn todas las reglas que
tengan como evento de disparo BeforeValidate, dado que inmediatamente despus ocurre la
validacin de la lnea; esto es una accin que ocurre a continuacin de haber terminado de
trabajar con la lnea.
Inmediatamente despus de la validacin de la lnea, se ejecutarn las reglas asociadas al
segundo nivel de la transaccin que incluyan en su definicin alguno de los eventos de disparo:
AfterValidate, BeforeInsert, BeforeUpdate, BeforeDelete.
Seguidamente a la ejecucin de las reglas asociadas al segundo nivel con alguno de estos eventos
de disparo se ejecutar la accin de grabacin; es decir, se grabar fsicamente la instancia
correspondiente a la lnea como registro fsico en la tabla correspondiente (en este ejemplo, en la
tabla: INVOICEDETAIL).
Inmediatamente despus de haberse grabado la instancia correspondiente a la lnea como registro
fsico en la tabla correspondiente:
si la grabacin correspondi a una insercin: se ejecutarn las reglas asociadas al segundo nivel
de la transaccin con evento de disparo AfterInsert.
si la grabacin correspondi a una actualizacin: se ejecutarn las reglas asociadas al segundo
nivel de la transaccin con evento de disparo AfterUpdate.
si la grabacin correspondi a una eliminacin: se ejecutarn las reglas asociadas al segundo
nivel de la transaccin con evento de disparo AfterDelete.
Todas de
estas
operaciones
sombreadas
gris claro,
se ejecutarn
en el
descrito,
cada
Luego
la iteracin
de todas
las lneas,depodemos
suponer
la existencia
de orden
una accin
que para
podramos
llamar
una
deabandono
las lneas.del segundo nivel. Luego de la misma se ejecutarn las reglas definidas con evento de
disparo AfterLevel Level Atributo del 2do nivel. Si no existe otro nivel, como es el caso del ejemplo,
entonces coincidir con el evento de disparo BeforeComplete.
131
Aclaracin importante: Todas las operaciones sombreadas, tanto en gris claro como en gris oscuro, se ejecutan
nicamente si se trata de una transaccin de dos niveles; de modo que cuando se trata de una transaccin de un
nivel, tales operaciones no se ejecutarn. El motivo de los dos sombreados distintos, es para diferenciar el
conjunto de operaciones que se ejecuta para cada una de las lneas (sombreado gris claro) de las operaciones
que se ejecutan solamente una vez finalizada la iteracin en las lneas (sombreado gris ms oscuro). A
continuacin seguimos explicando en orden, el resto de las operaciones que se ejecutan, as sea que se trate de
una transaccin de un nivel o dos.
Luego de haberse ejecutado todas las operaciones explicadas hasta el momento, se efectuar un commit,
A continuacin se ejecutarn las reglas con evento de disparo AfterComplete.
Es de fundamental importancia que quede claro que todas las operaciones explicadas se ejecutarn en el orden
en el que se han descrito, para cada factura con la cual se trabaje por medio de la transaccin "Invoice" (ya sea
que se ingrese, modifique o elimine).
Puede ser til tener en cuenta que se han resaltado en negrita las acciones cada vez que se las ha mencionado.
Las mismas son: validacin, grabacin , abandono del segundo nivel y commit.
Es indispensable asimilar el orden en el que se ejecutan las reglas en una transaccin, cules son los eventos de
disparo disponibles para asignarles, cundo se disparan exactamente, y qu acciones ocurren antes y despus de
cada evento de disparo, ya que solamente conocindolos bien se podr programar el comportamiento de las
transacciones adecuadamente. Es sencillo comprender que si necesitamos programar determinados controles o
acciones en las transacciones, tendremos que saber bien si hacerlo antes de que se grabe el cabezal, despus de
que se haya grabado el mismo, para cada una de las lneas despus de que se hayan grabado, o antes, despus
del commit o antes, por lo tanto es fundamental tener claro todo este tema.
132
Ejemplos
Cundo se dispararn las siguientes reglas?
Something.call( InvoiceId ) if Insert;
Luego de validado el campo InvoiceId e inferido que se est en modo Insert
133
Ejemplos
Algunas reglas estn mal programadas. Cules?
InvoiceDate = &today on AfterInsert;
Incorrecto: El ltimo momento para asignar valor a un atributo del cabezal
es inmediatamente antes de su grabacin (BeforeInsert)
134
Ejemplo 2
pgmname.call( CustomerId, &flag) On AfterComplete;
error('
') if &flag = 'N On AfterComplete;
135
En la primera alternativa, se ha definido una regla call y una regla error. Ambas reglas tienen el mismo
evento de disparo, y aparentemente existira dependencia entre ellas, ya que la regla de error est
condicionada al valor de la variable &flag, y la variable &flag se pasa por parmetro en la regla call.
Sin embargo, si bien la dependencia nos puede parecer evidente porque en el procedimiento programaremos
a la variable &flag, de salida, en la seccin de reglas de la transaccin -que es donde se encuentran las
reglas que estamos viendo-, el especificador de GeneXus no puede saber si los parmetros pasados en un
call son de entrada, de salida, o de entrada-salida; en consecuencia el especificador no encontrar
interdependencia entre las reglas call y error, ya que la variable &flag podra ser pasada como variable de
entrada al procedimiento, y en ese caso por ejemplo, no habra una dependencia por la cual primero se deba
ejecutar la regla call y luego la regla error.
As que concluyendo, no se detectan dependencias entre las reglas call y error de la alternativa 2.1), por lo
que las mismas se dispararn entonces en el orden en el que estn escritas. Es importante ver que si las
reglas call y error estuvieran escritas en orden inverso (es decir, primero la regla error y despus la regla
call), el comportamiento no ser el esperado en muchos casos.
Con respecto a la segunda alternativa, observemos que la misma consiste en una regla con udp y una regla
error. Ambas reglas tienen el mismo evento de disparo, y en este caso s existe dependencia entre ellas, ya
que la regla error est condicionada al valor de la variable &flag, y como la invocacin al procedimiento se
realiza con udp, para el especificador de GeneXus queda claro que la variable &flag vuelve modificada del
procedimiento; por lo tanto el especificador de GeneXus entiende que primero se debe disparar la invocacin
al procedimiento con udp y luego la regla error, porque la variable &flag se carga mediante la invocacin al
procedimiento con udp, y luego de que dicha variable tenga valor, es que habr que evaluar si disparar la
regla error, o no.
En el caso 2.2) entonces, independientemente del orden de definicin de ambas reglas, la invocacin al
procedimiento con udp se disparar primero, y luego de ello, se disparar la regla error (en caso de que se
cumpla la condicin de disparo, claro est).
Por esta razn se recomienda que siempre que se quieran definir validaciones de este tipo, se utilice udp en
lugar de call.
136
Eventos en Transacciones
En las transacciones se permite la programacin dirigida por eventos, que es un estilo de programacin en el
cul se define cdigo que permanece ocioso, hasta que suceden eventos provocados por el usuario o por el
sistema, que provocan que el cdigo definido se ejecute.
Los eventos son acciones reconocidas por un objeto que pueden suceder o no. A cada evento se le puede
asociar cdigo, que se ejecutar solamente si el evento se produce.
El cdigo que se le puede asociar a un evento se escribe siguiendo el estilo procedural; y cuando el evento se
produce, el cdigo asociado al mismo se ejecutar secuencialmente.
137
Eventos en Transacciones
Evento Start
Evento User Event
Evento After Trn
Evento Exit
Evento TrackContext
Como en Web no se mantiene un estado en el servidor que permita saber qu es lo que se ejecut en el
cliente, no es posible saber si se est ingresando la primera instancia de una factura, o si es la n-sima. Por
esta razn, se disparar el evento Start cada vez que se enve al servidor la informacin de la instancia con la
que se est trabajando.
En cuanto al evento Exit, se ejecutar por cada iteracin, al final de la misma.
El evento TrackContext apunta a obtener interfaces de usuario sensibles al contexto. Programando este evento
se podr recibir informacin del contexto para luego tomar las decisiones necesarias.
138
Eventos Start
Start: Se ejecuta cada vez que se somete el form de una
transaccinalservidor.
SINTAXIS: Event Start
cdigo
EndEvent
139
Eventos de Usuario
Adems de los eventos ofrecidos por GeneXus, el analista puede
definir eventos creados por l, llamados eventos de usuario.
Propiedades
Web:
Orden de
ejecucin
1. Evento Start
2. Lectura de atributos y variables del form
3. Evento de usuario seleccionado
Como se puede observar en la sintaxis, se le debe dar un nombre a un evento de usuario, debindose declarar
a continuacin de la palabra Event, encerrado entre comillas simples.
EJEMPLO:
Se desea que en la transaccin "Invoice", el usuario tenga la posibilidad de imprimir la factura con la cual est
trabajando, presionando el botn:
Event Print Invoice //evento definido en la transaccin "Invoice"
PrintInvoice.Call( InvoiceId )
EndEvent
Cmo asociar un evento de usuario a un control?
Adems de los botones, tambin las imgenes y los text blocks admiten la asociacin de evento de usuario.
Para realizar la asociacin se debe insertar el control correspondiente en el form Web y luego en las
propiedades del control, se deber seleccionar donde dice OnClickEvent uno de los eventos existentes, o se
puede crear uno nuevo. Volveremos sobre este tema en el captulo de Web Panels.
140
Ejemplo:
El evento After Trn de las transacciones ocurre inmediatamente despus de la ejecucin de las reglas con
evento de disparo AfterComplete. Por consiguiente, el cdigo que se incluya en este evento se ejecutar
luego de culminada cada iteracin completa por medio de la transaccin (es decir, luego de haberse
grabado cada cabezal con sus correspondientes lneas como registros fsicos en las tablas que
corresponda y de haberse efectuado COMMIT).
Existen las siguientes alternativas para programar comportamientos que se deseen ejecutar luego de cada
iteracin completa por medio de una transaccin:
1. Definir reglas individuales con evento de disparo AfterComplete y dejar el evento After Trn sin cdigo
2. Definir todas las sentencias en el evento After Trn con estilo procedural, y no definir reglas con evento de
disparo AfterComplete
3. Definir ambas cosas: algunas reglas con evento de disparo AfterComplete y cdigo en el evento After Trn
Como venimos explicando, primero se ejecutan las reglas definidas con evento de disparo AfterComplete, e
inmediatamente despus de las mismas se ejecuta el cdigo definido en el evento After Trn.
Un concepto que es muy importante tener claro es que tanto en reglas con evento de disparo AfterComplete
como en el evento After Trn, se conocen los valores de los atributos del primer nivel de la transaccin.
Es decir, si bien ya se grabaron fsicamente los registros correspondientes al cabezal y las lneas de cierta
iteracin completa, e incluso se efectu COMMIT, an se tienen disponibles los valores de los atributos del
primer nivel, pudiendo estos utilizarse para pasarlos por parmetro en una invocacin, o evaluar su valor, o
usarlos de algn modo salvo actualizarlos1.
--------------------------------------------------------------------------------------------------------------------------------------------------------------1 Hay dos motivos por los cuales no es posible actualizar atributos en reglas con evento de disparo AfterComplete ni en el
evento After Trn. El primer motivo es que ya se han hecho las grabaciones correspondientes e incluso se ha efectuado
COMMIT, de modo que ya es tarde para asignar valores a atributos. Y adems, en lo que respecta al evento After Trn, en
los eventos no se permite realizar asignaciones a atributos.
141
--------------------------------------------------------------------------------------------------------------------------------------------------------------1 Si en un evento de usuario se referencian atributos de un segundo nivel u otro nivel subordinado, cuando el evento de
usuario se ejecute se tendrn en cuenta los atributos de aquella lnea en la que se est posicionado; al momento de
ejecutarse el evento de usuario se considerarn los valores de los atributos de dicha lnea. Y si el usuario no se haba
posicionado explcitamente en determinada lnea, por defecto la lnea que estar seleccionada ser la primera, as que se
considerarn los valores de los atributos de la misma.
142
Integridad Transaccional
IT
143
Qu es el concepto:
integridad transaccional?
Un conjunto de actualizaciones a la base de datos tiene
integridadtransaccional cuandoencasode unafinalizacin
anormal, la base de datos permanece en estado
consistente.
Muchos manejadores de bases de datos (DBMSs) cuentan con sistemas de recuperacin ante fallos,
que permiten dejar la base de datos en estado consistente cuando ocurren imprevistos tales como
apagones o cadas del sistema.
144
Qu es el concepto:
unidad de trabajo lgica (UTL)?
Una unidad de trabajo lgica (UTL) es un conjunto de
operaciones a la base de datos, que deben ejecutarse o bien
todasobienningunadeellas.
Los manejadores de bases de datos (DBMSs) que ofrecen integridad transaccional permiten
establecer unidades de trabajo lgicas (UTLs), que corresponden ni ms ni menos que al concepto
de transacciones de base de datos.
145
Qu es efectuar COMMIT?
ElcomandoCOMMITpermiteespecificarqueciertoconjuntodeoperaciones
realizadas sobre una base de datos, ha culminado de efectuarse
correctamente:
...........
OperacinsobreBasedeDatos
COMMIT
COMMIT
OperacinsobreBasedeDatos
FinalizaUTL
ComienzaUTL
OperacinsobreBasedeDatos
OperacinsobreBasedeDatos
OperacinsobreBasedeDatos
OperacinsobreBasedeDatos
FinalizaUTL
DemodoqueefectuarCOMMITenunabasededatos,significaquesedapor
finalizadaunaunidaddetrabajolgica(UTL).
Podemos ver que una unidad de trabajo lgica (UTL) queda definida por el conjunto de operaciones
entre un par de Commits.
146
Qu es efectuar ROLLBACK?
HacerROLLBACK(vueltaaatrs)provocaquesedeshagan
todas las operaciones efectuadas en la base de datos que
nohayanquedadoconCOMMIT.
Esto se resuelve deshaciendo todas las operaciones
posterioresalltimoCOMMIT.
147
GeneXus
incluye
un
COMMIT
Es importante aclarar que GeneXus incluye la sentencia COMMIT en los programas generados
asociados a transacciones y procedimientos, slo en ambientes de trabajo Cliente/Servidor
(incluyendo, por tanto, los ambientes Web). El motivo de esto es que en ambientes Cliente/Servidor
existe un DBMS que asegura la integridad transaccional, por lo tanto GeneXus efecta la tarea de
definir las unidades de trabajo lgicas (UTLs).
Dnde incluye GeneXus COMMIT exactamente?
En cada procedimiento: al final del programa fuente.
En cada transaccin: inmediatamente antes de las reglas con evento de disparo AfterComplete (E
inmediatamente despus de las BeforeComplete). Es decir, que por cada iteracin completa que se
efecte en tiempo de ejecucin por medio de la transaccin, habr un COMMIT, justo antes de las
reglas con evento de disparo AfterComplete.
Nota: El tipo de datos Business Component que veremos ms adelante permite actualizar la base de
datos desde cualquier objeto GeneXus, pero tambin como veremos, no realiza automticamente un
COMMIT.
148
Personalizacin de UTL
en GeneXus
PropiedadCommit onExitdetransaccionesy
procedimientos:
Valores:
GeneXus ofrece una propiedad a nivel de cada objeto transaccin y procedimiento, para definir si se
desea que su programa generado efecte COMMIT, o no. El nombre de la propiedad es Commit on
Exit y su valor por defecto es Yes (por eso, toda transaccin y procedimiento por defecto efecta
COMMIT).
Si se desea que cierta transaccin o procedimiento no tenga en su programa generado COMMIT,
bastar con cambiar el valor de la propiedad Commit on Exit a No.
149
Personalizacin de UTL
en GeneXus
EjemplodeusodeCommit onExit=No
Trn. X
call
Proc. Y
Commit on Exit = No
150
Por ejemplo, para que la transaccin y procedimiento vistos conformen una nica UTL, podramos haber optado
tambin por la alternativa de que no efecte COMMIT la transaccin (Commit on Exit = No), sino que lo haga el
procedimiento al final de todo; y de hacerlo as, no sera un error como s lo sera en la solucin anteriorinvocar al procedimiento utilizando el evento de disparo AfterComplete, porque la transaccin no har COMMIT,
sino que lo har el procedimiento.
Concluyendo, es cuestin de decidir cul objeto har COMMIT y que las invocaciones que se deban hacer, se
hagan en momentos adecuados, para que la UTL personalizada quede bien definida.
Otro ejemplo:
Sea la transaccin Invoice estudiada hasta el momento. Supongamos que no modificamos el valor
predeterminado de la propiedad Commit on Exit.
Supongamos ahora que el usuario ejecuta la transaccin, ingresando la factura 1 con todas sus lneas. Luego
pasa a ingresar la factura 2 y cuando est ingresando la 3era. lnea de la misma, ocurre un apagn. Al
recuperarse la energa y reiniciarse la ejecucin, qu registros habrn quedado grabados en las tablas y cules
se habrn perdido?
La factura 1 ntegra estar grabada (cabezal y sus lneas). Por qu? Pues porque al terminar de ingresarla y
pasar a ingresar la factura 2, se efectu un Commit. La factura 2 con los registros que se haban grabado hasta
el momento de la falla de energa, se habr perdido. Por qu? Pues porque la transaccin realiza el rollback de
todo lo que se hubiere efectuado luego del ltimo Commit. El cabezal de la factura 2 y las 2 lneas que se haban
ingresado no estaban commiteadas an.
Observar entonces que el Commit no es por transaccin entera (es decir, todas las iteraciones del cabezal y sus
lneas) sino por cada instancia de cabezal + lneas.
Si el Commit se realizara una nica vez antes de cerrar la transaccin, entonces si se hubieran ingresado 29
facturas y a la trigsima se cayera el sistema, se perderan las 29 facturas anteriores (se deshara todo, ya que
an no se habra alcanzado el Commit). Esto no es as, y si ocurriera una cada del sistema a la trigsima factura
ingresada, las 29 anteriores quedarn grabadas (no as la trigsima).
151
Personalizacin de UTL
NopuededefinirseunaUTLcompuestaporvariastransaccionesWeb.
call
Trn.Y
Trn.X
UTL 1
UTL 2
UnatransaccinWebsolopuedeCommitear losregistrosinsertadosporellamisma,opor
procedimientosenunacadenadeinvocaciones,peronopuedeCommitear losregistrosinsertados
porotratransaccin.
call
Trn.X
(luego del
Trn.Y
Commit)
call
(antes del
Proc.Z
UTL
Commit)
En ambiente Web los registros visibles para ser commiteados por una transaccin son los
actualizados por la propia transaccin, y por los procedimientos que sta invoque antes de su
Commit, pero no los de otra transaccin.
Cada transaccin trabaja, as, sobre UTLs distintas.
Es por ello que en el primer ejemplo presentado arriba, donde la transaccin X llama a la
transaccin Y luego de haber insertado un registro, aunque la transaccin Y realice un Commit al
final de que cabezal y lneas sean ingresados, este Commit no valdr sobre el registro que haba sido
ingresado previamente por la transaccin X. Este registro quedar perdido, sin Commit.
Por la forma de trabajo en Internet, las transacciones Web viven solamente el tiempo entre que el
usuario de un navegador selecciona el link o presiona un botn y la nueva pgina es mostrada. Toda
modificacin a la base de datos que se haga durante la vida de la transaccin debe ser confirmada
o eliminada antes de que la Transaccin Web termine su ejecucin y retorne la pgina resultante.
Como consecuencia, una Transaccin Web inicia una UTL (unidad de trabajo lgica) al comenzar a
ejecutar y la cierra (ya sea por COMMIT o ROLLBACK) antes de terminar. No puede formar parte de
otra UTL. Si un programa llama a una Transaccin Web, sta iniciar otra (nueva) UTL.
En cambio no sucede lo mismo con los procedimientos. En el segundo ejemplo mostrado arriba,
vemos que podemos formar una UTL que engloba a la transaccin Y y al procedimiento Z sin
embargo no podemos incluir a la transaccin X en la misma UTL.
152
Personalizacin de UTL
Sideseamosquelasinsercionesmediantedostransaccionesdistintas
conformenunanicaUTL:
Trn.X
Trn.Y
Tenemosunasolucin:utilizarBusinessComponents yelcomandoCommit al
terminardeinsertarmediantelasvariablesBusinessComponents losregistros
asociadosaambastransacciones(sever msadelante).
Si se necesita que las operaciones de dos o ms transacciones (con o sin procedimientos incluidos)
conformen una misma UTL, se pueden emular las transacciones con Web panels y Business
Components y utilizar el comando Commit.
Dejamos aqu anotado simplemente el tema, para volver a l luego de estudiados los Business
Components, donde nos ser posible comprender esta solucin.
153
154
Objeto Procedimiento
155
Procedimientos
Definicin
Procesos nointeractivos deconsulta yactualizacin delabase
dedatos.
Procedimientos:
Definen procesos no interactivos de consulta y actualizacin de la base de datos. Los procedimientos
pueden generar un archivo formato PDF, mediante el cual es posible listar informacin por pantalla o
impresora. Adems, los procedimientos pueden actualizar la base de datos1.
-------------------------------------------------------------------------------------------------------------------------------1 Como veremos ms adelante, existe un tipo de datos especial, que no es estrictamente un tipo de datos, sino
algo un poco ms complejo, el business component, por medio del cul se podrn realizar actualizaciones a la
base de datos en cualquier objeto GeneXus. Por tanto, utilizando variables de tipo de datos business component,
podrn realizarse actualizaciones incluso en los objetos que por naturaleza no ofrecen esta posibilidad, como los
web panels.
156
Caractersticas
Definicinprocedural.
Definicinsobrelabasedeconocimiento.
Independenciadelabasededatos:definicinanivelde
atributos.
Definicin procedural
A diferencia de las reglas de las transacciones donde las especificaciones se realizan en forma
declarativa y GeneXus determina en el momento de generar el programa la secuencia de ejecucin,
en los los procedimientos las especificaciones se realizan en forma procedural. De esta forma, la
secuencia de ejecucin es determinada por el analista, utilizando para ello un lenguaje bastante
simple que contiene comandos de control, de impresin, de acceso a la base de datos, etc.
Definicin sobre la base de conocimiento
La gran potencia del lenguaje de los procedimientos radica en que las definiciones se hacen sobre la
base de conocimiento y no directamente sobre el modelo fsico (tablas, ndices, etc.). Esto nos
permite utilizar automticamente todo el conocimiento ya incorporado o generado por GeneXus a
partir de las especificaciones realizadas.
Por ejemplo, si deseamos desplegar el resultado de una frmula alcanza con nombrar al atributo
frmula en el lugar adecuado y GeneXus disparar su clculo desplegando el resultado, sin
necesidad de que el analista tenga que brindar ninguna otra informacin. La informacin de cmo se
calcula un atributo frmula est contenida en la base de conocimiento.
Tambin podremos utilizar el concepto de tabla extendida, ya que GeneXus conoce las relaciones
entre las tablas de la base de datos, por lo que el analista no necesita explicitar estas relaciones a la
hora de recuperar datos.
Independencia de la base de datos: definicin a nivel de atributos
La definicin de los procedimientos se hace a nivel de atributos: no es necesario indicar
explcitamente cules tablas sern recorridas ni mediante qu ndices. Con solo mencionar los
atributos a los que se desea acceder es suficiente para que GeneXus determine esta informacin.
Esto es posible porque GeneXus tiene un completo conocimiento de la estructura de la base de
datos.
De esta manera logramos una real independencia de la base de datos, ya que cualquier cambio en
las tablas ser manejado automticamente por GeneXus y de esta forma, para actualizar los
programas alcanzar, gran parte de las veces, con regenerar los objetos sin tener que modificar nada
de lo programado en ellos.
157
Elementos
Comoenlastransacciones,puedendefinirsevariablesquesern
localesalobjeto.
-------------------------------------------------------------------------------------------------------------------------------1
158
Ejemplo
Queremosimplementarunlistadocomoelquesigue:
rea con datos fijos
rea con datos fijos
Por ejemplo, supongamos que queremos implementar un procedimiento para imprimir el identificador,
nombre y pas de todos nuestros clientes y queremos que el listado luzca como se muestra en la
figura.
Para ello, debemos identificar en la salida del listado las distintas reas que lo componen. A cada una
de ellas la representaremos con un Printblock.
Los primeros dos Printblocks lucirn en GeneXus tal cul las primeras dos reas sealadas pues
stas contienen nicamente textos, lneas, recuadros. Tambin podramos haber fusionado estas dos
reas convirtindolas en una y utilizando por tanto un nico Printblock.
El tercer Printblock ser el correspondiente al rea de datos variables de la figura anterior, que
representa informacin que debe ser extrada de la base de datos.
Lo que queremos mostrar en este caso es el identificador y nombre de cada cliente, junto con el
nombre del pas al que pertenece. Esta informacin es la representada por los atributos CustomerId,
CustomerName y CountryName de la base de conocimiento de la aplicacin, por lo que el tercer
Printblock contendr los tres controles atributo CustomerId, CustomerName y CountryName.
Transformando las reas en Printblocks, el Layout del procedimiento nos quedar como el que figura
en la pgina siguiente.
159
Layout
Nombre de cada Printblock
Printblock
SucesindePrintblocks.
Noimportaelordendedefinicin.
CadaPrintblock debetenerunnombrenico.
Solosedeclaran,soninvocadosdesdeelSource conel
comandoprint (Ej.:print header).
El Layout de un procedimiento ser una sucesin de Printblocks que no tienen por qu seguir el
orden en el que se desea que aparezcan en la salida.
En el ejemplo anterior, el mismo procedimiento habra sido impreso si se hubieran especificado los
Printblocks en el orden inverso (o en cualquier orden).
Aqu simplemente se declaran. El orden en el que se ejecutan queda determinado en la seccin
Source que es la que contiene la lgica del procedimiento. Desde all sern invocados mediante un
comando especfico para tal fin (el comando print).
Por esta razn, cada Printblock deber tener un nombre nico para poder ser referenciado luego desde
el Source.
En el ejemplo, para listar todos los clientes, el Printblock de nombre customer deber ser invocado
dentro de una estructura repetitiva en el Source. Esta estructura repetitiva es el comando For each que
estudiaremos luego.
160
Layout: Printblock
ParadefinirlosPrintblocks tenemoslossiguientes
controlesdisponibles:
161
Source
Definelalgicadelprocedimientomedianteprogramacin
procedural
Lenguajemuysimple
Comandosusualesdecontrol:If,Docase,Dowhile,For
Comandosdeimpresin:Print,Header,Footer
ComandodeaccesoyactualizacindelaBD:For each,New,Delete
Comandosparasalirdeunbucle,abandonarelprograma,invocaraotro
objeto,invocaraunasubrutina,etc.:Exit,Return,Call,Do
162
La definicin del acceso a la base de datos para recuperacin de informacin se realiza con un nico
comando: el comando For each1.
Usando el For each se define la informacin a la que se va a acceder. La forma de hacerlo se basa en
nombrar los atributos a utilizar.
As, con este comando se definen qu atributos se necesitan y en qu orden se van a recuperar, y
GeneXus se encarga de encontrar cmo hacerlo. No se especifica de qu tablas se deben obtener, ni
qu ndices se deben utilizar para acceder a esas tablas: eso lo inferir GeneXus. Evidentemente esto
no siempre es posible, y en tales casos GeneXus da una serie de mensajes de error indicando por qu
no se pueden relacionar los atributos involucrados.
La razn por la cul no se hace referencia al modelo fsico de datos es porque de esta manera la
especificacin del procedimiento es del ms alto nivel posible, de tal forma que ante cambios en la
estructura de la base de datos la especificacin del mismo se mantenga vlida la mayor parte de las
veces.
Cuando aparece un For each se est indicando que se quiere recuperar informacin de la base de
datos. Concretamente GeneXus sabe que con un For each se quiere recorrer (o navegar) una tabla.
Para cada registro de esa tabla, se quiere hacer algo con la informacin asociada (ej: imprimirla).
Por lo tanto, todo comando For each tendr una tabla fsica asociada: la tabla que ser recorrida o
navegada. A esta tabla la llamaremos tabla base del For each.
---------------------------------------------------------------------------------------------------------------------------------1 Cuando estudiemos los business components veremos que utilizando su mtodo Load tambin se consigue
consultar la base de datos.
163
COUNTRY
Layout:
Source:
For each
print customer
Endfor
Intuitivamente resulta claro que con este comando estamos queriendo listar identificador, nombre y
pas de cada uno de los clientes de la base de datos. Es decir, queremos que se recorra la tabla
CUSTOMER, y para cada cliente se recupere de la tabla COUNTRY el nombre del pas al que
pertenece, imprimiendo esta informacin, junto con el identificador y nombre del cliente. (Observar
que la tabla COUNTRY pertenece a la extendida de CUSTOMER)
Cmo infiere esto GeneXus si todo lo que hicimos en el For each del ejemplo fue nombrar los
atributos que nos interesaba mostrar?
164
COUNTRY
INTERPRETACIN:
For each record in CUSTOMER table
Find the corresponding CountryName in table COUNTRY
print customer
Endfor
Dentro de todo For each se navega -recorre o itera- la tabla base, pero puede accederse a las
tablas que constituyen su tabla extendida para recuperar informacin, que por pertenecer a la
extendida estar unvocamente relacionada con cada registro de la tabla base con el que se est
trabajando en cada iteracin (el concepto de tabla extendida es muy importante en este comando y
sugerimos repasar su definicin).
Es por ello que en el For each del ejemplo, la tabla base ser CUSTOMER, y adems se acceder
para cada cliente, no solo a los datos de su registro, sino a los del registro asociado en la tabla
COUNTRY (que est en la extendida de CUSTOMER). Decimos entonces que se recorre
CUSTOMER y se accede adems a COUNTRY para buscar el resto de la informacin requerida.
Como podemos ver claramente en el ejemplo presentado, no le damos explcitamente a GeneXus
esta informacin. No es necesario, ya que GeneXus conoce las relaciones entre las tablas, y en base
a los atributos mencionados dentro del For each, puede encontrar sin necesidad de ms informacin
una tabla extendida que los contenga.
La tabla base de esa extendida es la que elige como tabla base del For each.
165
A la tabla base correspondiente a esa tabla extendida la llamaremos tabla base del For each y ser
recorrida en forma secuencial, ejecutando para cada registro lo que se indique en los comandos
internos al For each.
166
Pero:
ext(CUSTOMER) < ext(INVOICE)
ext(CUSTOMER) es la mnima
tabla extendida que contiene a los
atributos del For each.
Para el ejemplo presentado en el que se quieren listar de cada uno de los clientes su identificador,
nombre y nombre de pas, si observamos los atributos utilizados dentro del For each, vemos que ellos
son los contenidos en el Printblock de nombre customer: CustomerId, CustomerName y
CountryName.
En qu tablas estn estos atributos?
CustomerId est en 2 tablas:
- CUSTOMER como clave primaria (PK).
- INVOICE como clave fornea (FK).
CustomerName est solo en CUSTOMER (es un atributo secundario).
CountryName est solo en COUNTRY (es un atributo secundario).
GeneXus conoce las relaciones entre las tablas. Podemos ver el diagrama correspondiente a las
tablas en las cuales aparecen los atributos del For each (Tools/Diagrams).
Aqu puede verse claramente el por qu del requerimiento de que la tabla extendida sea la mnima
(entendiendo por mnima aquella que involucra menor cantidad de tablas). La tabla extendida de
INVOICE tambin contiene a todos los atributos del For each, pero no es mnima, pues la de
CUSTOMER tambin los contiene.
Por lo tanto, se va a recorrer secuencialmente la tabla CUSTOMER, y para cada registro de esa
tabla, se va a acceder a la tabla COUNTRY, para recuperar el registro de la misma que cumpla:
COUNTRY.CountryId = CUSTOMER.CountryId y para el mismo se va a recuperar el valor del atributo
CountryName, para poder imprimirlo, junto con el cdigo y nombre del cliente.
167
Listado de navegacin
tabla base
Se resuelve la consulta ordenada
por la PK de la tabla base
Listado de navegacin
GeneXus ofrece para todos sus objetos un listado conocido como listado de navegacin, que es el
resultado de la especificacin del objeto. Este listado es muy til para los procedimientos, ya que
indica cules son las tablas que se estn accediendo en cada For each del Source, si existe un ndice
para recuperar los datos de la tabla base, y en caso de que as sea cul es ese ndice (su nombre), si
se aplican filtros sobre los datos o se van a listar todos, etc.
De esta manera, el analista no tiene que ejecutar el objeto para verificar que la lgica sea la
esperada. Con estudiar el listado de navegacin ya tiene la informacin necesaria para saber si se
est recorriendo la tabla esperada, si se estn aplicando correctamente los filtros deseados, etc.
Como puede verse en el listado correspondiente al procedimiento del ejemplo, muestra para el
comando For each del Source, cul es su tabla base, por qu orden se va a resolver esa consulta
(ser el orden en el que se imprimirn los resultados), si existe un ndice que satisfaga ese orden cul
es su nombre, y adems aparecen dos elementos ms: los filtros de navegacin y el diagrama de
tablas.
Los filtros de la navegacin indican qu rango de la tabla base se va a a recorrer. En el ejemplo se
va a recorrer toda la tabla base del For each: empezando por el primer registro de CUSTOMER, y
hasta que se alcance el fin de tabla (utilizando el ndice ICUSTOMER).
Tambin se muestra en un pequeo diagrama de tablas, la tabla base del For each con su clave
primaria, e indentadas todas las tablas de la extendida que deban accederse para recuperar
informacin asociada al registro de la tabla base con el que se est trabajando en cada iteracin del
For each. En este caso se muestra solamente la tabla COUNTRY.
En el comando For each del ejemplo no aparece explcitamente ninguna informacin respecto al
orden en el que queremos que se imprima la informacin. En este caso GeneXus elige como orden la
clave primaria de la tabla base del For each. Es por esta razn que para el For each del ejemplo
GeneXus determin que el orden ser el correspondiente al atributo CustomerId, clave primaria de la
tabla CUSTOMER.
168
Soloparalosregistrosquecumplanlascondicionesbooleanas
delasclusulaswhere debenejecutarseloscomandosinternos
alFor each.
Lasclusulaswhere aplicanslosisesatisfacenlascondiciones
desusclusulaswhen.
Para restringir los datos que se quieren listar en un For each se utilizan las clusulas where del
comando.
Si en el listado de clientes no queremos listar todos los clientes, sino solo aquellos cuyo nombre est
dentro de un rango ingresado por el usuario, entonces debemos agregar al For each que habamos
visto una cllusula where, para especificar los filtros deseados sobre los datos:
For each
where (CustomerName >= &Start) and (CustomerName <= &End)
print customer
Endfor
donde las variables &Start y &End deben definirse en el procedimiento con el mismo tipo de datos
que CustomerName, y cargarse con valores fijos recibidos por parmetro1.
Con la clusula where definida le estamos diciendo a GeneXus que no queremos quedarnos con
todos los registros de la tabla base, sino solo con aquellos para los que se satisfaga la condicin
booleana de la clusula.
En el ejemplo escribimos una sola clusula where con una condicin compuesta, pero podramos
haber programado lo mismo con dos clusulas where, como se muestra arriba en la transparencia.
Es decir, cuando aparecen varios where la condicin de filtro que se va a aplicar sobre los datos es
la conjuncin booleana de todas las condiciones de los where que aparezcan.
Observemos que en la transparencia las clusulas where estn a su vez condicionadas con
clasulas when. Esto se lee de la siguiente forma: se aplicar el filtro establecido por el where solo
cuando se satisfaga la condicin del when.
En el ejemplo, solo se aplicar el primer filtro: CustomerName >= &Start si la variable &Start no est
vaca. Si est vaca, este filtro no se aplicar. Anlogo es el caso de la segunda clusula when.
Observar que si &Start y &End estn vacos, no aplicar ninguna de las clusulas where, y por tanto
se listarn todos los clientes (como si las clusulas where no hubiesen sido escritas).
Cada condicin booleana de un where puede estar compuesta de varias expresiones booleanas
concatenadas con los operadores lgicos and, or y not.
-------------------------------------------------------------------------------------------------------------------------------------------------1 A travs de un objeto que los pide al usuario, por ejemplo un Web Panel.
169
Listado de navegacin
Listado de navegacin
Aparece un nuevo elemento en este listado que no estaba presente antes, cuando no tenamos
clusulas where: las constraints (restricciones).
Qu informacin nos brinda este listado de navegacin?
que la tabla base del For each seguir siendo CUSTOMER
que se seguir ordenando la consulta por CustomerId, utilizando el ndice ICUSTOMER
correspondiente
que seguir recorriendo toda la tabla CUSTOMER en busca de la informacin
pero que para cada cliente evaluar si cumple con las restricciones que aparecen enumeradas
(CustomerName>= &Start si &Start no est vaca y CustomerName<=&End si &End no est vaca) y
solo en caso de que las cumpla, ejecutar para ese cliente los comandos que aparecen dentro del
For each. En este caso, imprimir los valores de los atributos del Printblock customer: CustomerId,
CustomerName, CountryName.
que debe acceder a la tabla COUNTRY cuya clave primaria es CountryId para obtener algn dato
(CountryName)
170
Los atributos utilizados en las condiciones de filtro pueden ser cualesquiera de la tabla extendida del
For each.
En el ejemplo, si bien la tabla base del For each es CUSTOMER, estamos filtrando los datos a
recuperar utilizando el atributo CountryName, que es de la tabla COUNTRY, perteneciente a la
extendida de CUSTOMER.
En este ejemplo tampoco se explicita nada con respecto al orden, por lo cul los datos aparecern
ordenados por la clave primaria de la tabla base, es decir, por identificador de cliente, CustomerId.
171
Paradeterminarordendescendentesedebencolocarparntesis
rodeandoalosatributosdelorden.Ej:order (CustomerName)
Si queremos realizar un listado de todos los clientes pero ordenado por nombre del cliente en lugar
de por cdigo, lo nico que tenemos que hacer es modificar el comando For each agregando esta
informacin del orden.
Esto se logra utilizando la clusula order del For each, como se muestra en el primer ejemplo.
Como no existe un ndice definido en la tabla CUSTOMER por el atributo CustomerName, GeneXus
indicar en el listado de navegacin mediante una advertencia (warning) que no existe un ndice
para satisfacer el orden, lo que podra ocasionar problemas de performance, dependiendo de la
plataforma de implementacin elegida, de la cantidad de registros que deben ser ledos de la tabla,
etc.
En ambientes cliente/servidor, si no existe ndice para satisfacer el orden, el For each se traduce en
una consulta SQL (select) que es resuelta por el motor del DBMS de la plataforma.
Al igual que en el caso de las clusulas where, la clusula order puede condicionarse, como se
muestra en el segundo ejemplo. En caso de no cumplirse la condicin del when, no aplicar ese
orden y de no existir orden incondicional (sin clusula when) como en el ejemplo, el orden a utilizar
ser indefinido, significando esto que el orden resultante podr variar de DBMS a DBMS e incluso
entre ejecuciones sucesivas.
Pueden especificarse varias clusulas order condicionadas (con clusula when) consecutivas y
una sin condicin (la ltima de la lista). La primera clusula order cuya condicin del when se
satisfaga, ser la elegida y su orden el utilizado.
Clusula Order None: clusula que evita que GeneXus elija por defecto el orden de los atributos de
la clave primaria de la tabla base y utilice un orden de navegacin indefinido.
Si se utiliza la clusula Order None, GeneXus entiende que no desea establecer ningn orden de
recorrida en particular y delega esta tarea al DBMS.
La clusula order none admite condicin para aplicarse (when).
172
Listado de navegacin
Listado de navegacin
Cuando no existe ndice que satisfaga el orden de un For each, como es el caso del ejemplo, el
analista GeneXus puede resolver crearlo (ndice de usuario). En la mayora de los casos el
procedimiento ser bastante ms eficiente de esta manera, pero se debe mantener un ndice ms (lo
que implica mayor almacenamiento y mayor procesamiento para mantener actualizado el ndice)
No es posible recomendar a priori cul de las dos soluciones es la mejor (no ndice vs ndice de
usuario), por lo tanto se debe estudiar, caso por caso, la solucin particular teniendo en cuenta la
plataforma de implementacin y siendo fundamental la frecuencia con que se ejecutar el
procedimiento. De cualquier manera, si al comienzo no se defini el ndice de usuario y
posteriormente se decide definirlo, alcanza con regenerar el procedimiento (sin modificar nada de lo
programado en el mismo) y ste pasar a utilizarlo.
El listado de navegacin anterior nos informa que:
la tabla base del For each es CUSTOMER
y se recorrer ordenada por CustomerName
no existe un ndice definido para ese atributo
se recorrer toda la tabla CUSTOMER con el orden especificado
no hay condiciones de filtro, por lo que para todos los registros de la tabla se ejecutarn los
comandos dentro del For each (en nuestro caso, el comando print).
173
OPTIMIZACIN:
Orden compatible con los filtros
For each
where CustomerName >= &Start
where CustomerName <= &End
print customer
Endfor
Se recorre
toda
la tabla base
No se recorre
toda
la tabla base:
optimizado!
Si nos interesa filtrar los clientes de forma tal que sus nombres pertenezcan a un rango, en el primer
ejemplo, como no especificamos clusula order GeneXus ordena por clave primaria, es decir, por
CustomerId.
En este caso, el listado de navegacin nos va a informar que se debe recorrer toda la tabla
CUSTOMER, y para cada registro de la misma se debe evaluar si el registro cumple o no con las
condiciones (restricciones o constraints). En caso afirmativo, se imprimen para el mismo los datos
correspondientes.
Si en lugar de ordenar los datos por CustomerId pedimos que se ordenen por CustomerName, como
se presenta en el segundo ejemplo, la tabla base se recorre ordenada por CustomerName y como en
los filtros establecemos que queremos quedarnos solo con aquellos clientes cuyo nombre,
CustomerName, est en el rango determinado, entonces ya no ser necesario recorrer toda la tabla
base para obtener los datos que cumplen con las condiciones!
Diremos que esta segunda consulta est optimizada en ese sentido. Tener en cuenta, sin embargo,
que GeneXus no tiene creado un ndice en forma automtica por CustomerName, y aqu habr que
evaluar si conviene crear un ndice de usuario (que debe ser mantenido por Genexus luego) o no
crear ndice y que se cree un ndice temporal en ejecucin para resolver la consulta si el DBMS no
puede resolverlo de otra forma.
El listado de navegacin nos informar si una consulta est o no optimizada, de acuerdo a si
recorrer toda la tabla (desde First Record hasta End of table) o si recorrer por el contrario un
rango ms reducido.
174
OPTIMIZACIN:
Orden compatible con los filtros
GeneXus siempre
intentar
encontrar el mejor
orden posible para
que la consulta
sea optimizable,
es decir, coincida
con algn ndice
definido en la
base de datos.
El listado de navegacin nos informa que la consulta est optimizada ya que recorre solamente los
registros incluidos en el filtro (desde CustomerName>=&Start hasta CustomerName <=&End).
Para determinar el orden se tiene en cuenta:
Los atributos de la clusula Order especificada por el usuario
Las restricciones que aplican al nivel (atributos mencionados en la regla Parm del procedimiento,
condiciones explcitas tanto en el Where como en las Conditions)
La existencia de ndices sobre estos atributos.
Distinguimos 2 casos:
1) Se escribe una clusula order
El For each quedar ordenado por esos atributos, exista o no un ndice por stos.
Si no existe un ndice con los atributos del order, pero existen condiciones implcitas o
condiciones explcitas por igualdad, se busca si existe un ndice que contenga los atributos
de las condiciones ms los del Order. La condicin explcita prevalece sobre la mplcita para
la determinacin del Order, en caso que sean diferentes y exista ndice por cada una de
ellas.
Si existe un ndice, los atributos de las condiciones sern agregados en la lista del Order
para que dicho ndice sea considerado en su lugar.
2) No se escribe clusula order
En este caso, si existe algn ndice por los atributos de la condicin, el Order quedar
determinado por los atributos del ndice.
Si no existe un ndice que corresponda con las condiciones, o sea que no se puede
optimizar la recorrida segn las condiciones del nivel, entonces se ordenar por los atributos
de la Primary Key.
175
CITY
{
CountryId*
CityId*
}
El For each:
For Each order CityId
Where CountryId = 1
...
Endfor
Recorrer la tabla CITY, ordenando por: CountryId, CityId y utilizando el ndice ICITY (ndice por
clave primaria que contiene ambos atributos).
Aunque es el propio DBMS el que resuelve el plan de acceso ms apropiado, la informacin antes
mencionada influir en su determinacin.
176
For each:
clusula Defined by
For each
defined by InvoiceDate
print customer
Endfor
Noofrecefuncionalidadalgunaenloquerespectaalosdatosa
recuperar.
Seutilizaexclusivamenteparadarunelementomsparala
determinacindelatablabasedelFor each deseada.
Ejemplo: Mn. extendida que contiene a InvoiceDate,
CustomerId, CustomerName, CountryName:
ext(INVOICE) tabla base INVOICE
Puede darse el caso de que para un For each haya ms de una tabla base cuya extendida contenga a los
atributos del For each, siendo mnima. Ante esta ambigedad, GeneXus escoge la primera de estas tablas
extendidas mnimas.
Para resolver este tipo de ambigedad surge la clusula defined by, que permite nombrar atributos de la tabla
base deseada, que no se utilizarn para devolver la consulta ordenada por esos atributos, ni para filtrar la
informacin a recuperar, ni para ser desplegados en el listado (es decir, no tienen funcionalidad alguna con
respecto a los datos a recuperar), sino solo para aportar ms informacin que permita determinar la tabla
base del For each.
En la clusula Defined by se debe hacer referencia a por lo menos un atributo de la tabla base deseada.
De la misma manera, se puede (y se suele) utilizar para modificar la que sera la tabla base en caso de no
nombrarse ningn atributo ms dentro del For each. Este es el caso del ejemplo presentado, en el que no
queremos listar todos los clientes de la tabla CUSTOMER, sino por el contrario, queremos listar todos los clientes
de las facturas. De no nombrarse dentro del For each algn atributo de INVOICE, la tabla base sera
CUSTOMER.
En la mayora de los casos no es necesario utilizar esta clusula. Sin embargo, para procedimientos ms o
menos complejos, an cuando no exista problema de ambigedad, se recomienda el uso del Defined by porque
mejora bastante el tiempo de especificacin del procedimiento.
Sin embargo, no puede aconsejarse un uso indiscriminado. La contra de utilizar esta clusula cuando no es
necesaria es que ata un poco ms el cdigo al diseo de las tablas.
Supngase por ejemplo que no se tiene creada una tabla COUNTRY, y se tiene de cada cliente el pas al que
pertenece, como atributo secundario. Si lo que queremos es listar los clientes y su pas, seran equivalentes:
For each
print customer
Endfor
For each
Defined by CountryName
print customer
Endfor
177
For each:
clusula Defined by
Atributospermitidos:puedenaparecervariosatributosdela
tablaextendida,peroalmenosunodebecorresponderalatabla
basequesedesea(encasocontrariodar unerror).
Sesugiereutilizaratributossecundarios,dadoquelosmismos
estnenunanicatabladelmodeloyestoevitaambigedades.
Pueden aparecer varios atributos, para el posible caso en el que no alcance uno solo para determinar
completamente la tabla base deseada, donde al menos uno de ellos deber estar asociado a la tabla
base deseada.
Se recomienda el uso en el Defined by de atributos secundarios de la tabla base que se desea
navegar, ya que como sabemos, los atributos secundarios solo pueden estar en una tabla del modelo
y de esta forma eliminamos por completo toda posible ambigedad.
Esto sin embargo, no es obligatorio, es decir, pueden nombrarse en el Defined by atributos primarios
cuando se sepa que no habr ambigedad en la eleccin de la tabla base.
Un error comn es creer que cuando un For each tiene esta clusula, la tabla base del mismo queda
determinada exclusivamente a partir de los atributos mencionados en el defined by.
La realidad es que los atributos del defined by arrojan una o ms tablas base candidatas a ser la
tabla base del For each, pero luego hay que ver si tomando cada tabla base candidata, su extendida
contiene a todos los dems atributos del For each, adems de los del defined by.
Si ninguna de las posibles tablas base candidatas cumplen esta condicin, entonces el procedimiento
dar un error al ser especificado, y no podr ser generado (recordemos que debe cumplirse que
todos los atributos del For each estn contenidos en una misma tabla extendida).
178
For each:
clusula When none
PermiteejecutardeterminadocdigocuandoenunFor each no
seencuentraningnregistroquecumplalascondiciones.
Ejemplo:
For each
where CustomerName >= &Start
where CustomerName <= &End
print customer
When none
print message
Endfor
El Printblock message (que podr contener un texto advirtiendo al usuario de que no existen clientes
que cumplan los filtros) se ejecuta slo cuando no se entra en el For each, es decir, cuando no hay
ningn registro correspondiente a la tabla base del For each para el que se cumplan las condiciones
de filtro.
Tambin se aplica a For each [selected] line, XFor Each y XFor First, comandos que veremos ms
adelante.
La clusula When none debe ser la ltima dentro del For each. Las acciones a realizar cuando no
existe ningn registro para el que se cumplan las condiciones, quedan determinadas por el bloque de
cdigo que hay entre la clusula When none del For each y el Endfor.
Cuando un For each no tiene condiciones de filtro, los comandos del When none se ejecutarn solo
en el caso en que se cumpla que la tabla base del For each est vaca, porque solo en ese caso no
habr ningn registro que cumpla las condiciones de filtro.
Importante:
Si aparecen atributos en el bloque de cdigo correspondiente al When none, stos no son tenidos
en cuenta para determinar la tabla base del For each.
Si se incluyen For eachs dentro del When none no se infieren Joins ni filtros de ningn tipo con
respecto al For each que contiene el When none, ya que son considerados For eachs paralelos.
179
180
Eleccin del ndice: GeneXus elige automticamente el ndice a utilizar para satisfacer el orden. GeneXus siempre
intentar encontrar el mejor orden posible para que la consulta sea optimizable, es decir, coincida con algn ndice
definido en la base de datos. Para determinar el orden se tiene en cuenta:
Los atributos de la clusula Order especificada por el usuario
Las restricciones que aplican al nivel (atributos mencionados en la regla Parm del procedimiento, condiciones
explcitas tanto en el Where como en las Conditions)
La existencia de ndices sobre estos atributos.
Aunque es el propio DBMS el que resuelve el plan de acceso ms apropiado, la informacin antes mencionada
influir en su determinacin.
Los atributos del order son tenidos en cuenta a la hora de determinar la tabla base del For each. Pero ellos por s
solos no la determinan. Deben examinarse tambin otras partes del For each.
Using DataSelectorName
Permite definir filtros acorde al criterio definido en el DataSelector1 definido en DataSelectorName.
Where Condition
Condicin booleana que debern cumplir los datos para ser procesados dentro del For each, pudiendo ser una
condicin compuesta, utilizando los operadores lgicos and, or y not.
Los atributos que aparezcan en la condicin booleana pueden ser tanto de la tabla base del For each como de la
extendida.
Como se desprende de la sintaxis, para un mismo For each pueden especificarse n clusulas where sucesivas,
cada una con una condicin:
where cond1
where cond2
...
where condn
La ocurrencia de n clusulas where es equivalente a la ocurrencia de una sola clusula, con la conjuncin booleana
de las condiciones:
where cond1 and cond2 and and condn
Los datos de la tabla extendida del For each que cumplan con todas las condiciones de los where sern los
procesados en los comandos internos al For each (los del bloque de cdigo code1).
Al igual que ocurre con la clusula order, podrn condicionarse los filtros (con clusulas when). De esta manera,
primero se evala la clusula when de cada clusula where, y de cumplirse su condicin, aplicarn el filtro
especificado en el where.
Nota: Existe tambin la clusula Option Distinct del For Each que permite retornar los registros que cumplan
unicidad de valores de los atributos referenciados. No veremos esta clusula. El lector interesado puede recurrir a
las distintas fuentes de documentacin para estudiarla (Help, Wiki)
181
Defined by
defined_attributes::= att1, att2,,attp
Es un conjunto de atributos que sern utilizados a los solos efectos de determinar la tabla base del For each.
Al mencionar aqu algunos atributos de la tabla que se desea recorrer, stos participarn en la determinacin de la
tabla base del For each.
La clusula defined by aparece para solucionar algunos problemas de ambigedad en la determinacin de la tabla
base (cuando existen varias tablas extendidas mnimas que contienen a los atributos del For each) o cuando se
desea que la tabla base sea otra, distinta de la que sera determinada por los atributos que aparecen en el resto del
For each (este caso cobrar sentido cuando se estudie corte de control). Tambin se utiliza para mejorar el tiempo
de especificacin en procedimientos complejos.
Los atributos de esta clusula no determinan por s solos la tabla base del For each. Podra darse el caso de que de
estos atributos surja determinada tabla como la candidata a tabla base, pero si luego el resto de los atributos del
For each no estn contenidos en la extendida de esa tabla, el For each dar un error y el objeto que lo contiene no
podr ser generado.
code1
Es una sucesin de comandos en los que pueden utilizarse atributos de la tabla extendida del For each. A este
bloque de cdigo le llamaremos cuerpo del For each.
Los atributos que figuren en este bloque de cdigo participarn en la determinacin de la tabla base del For each.
Los comandos especificados se ejecutarn secuencialmente para los datos de la tabla extendida que cumplan las
condiciones de filtro, considerndose los datos en el orden especificado.
Blocking
Si bien se abordar este tema ms adelante en el curso, a modo de idea general diremos que la especificacin de
esta clusula permite realizar actualizaciones y eliminaciones en bloque, reduciendo as el nmero de accesos a la
base de datos.
When Duplicate
Esta clusula solo tiene sentido en procedimientos (dado que tiene que ver con la actualizacin) y se ver ms
adelante.
Se ejecutar esta clusula si dentro del cuerpo del For each code1, se intenta actualizar un atributo que es clave
candidata (tiene ndice unique) y ya existe un registro con ese valor. GeneXus utiliza el ndice unique para asegurar
la unicidad de esa clave candidata y en caso de encontrar duplicados, si el For each tiene programada esta
clusula, ejecutar su cdigo: code2 .
De no existir la clusula no se ejecutar cdigo alguno.
When none
En caso de que no existan datos que cumplan las condiciones de filtro no se ejecutarn los comandos del code1
sino que se ejecutarn los del bloque de cdigo code3.
Tanto para When Duplicate como para When none: Si se incluye dentro de alguno de los dos un comando For
each, no se infieren joins ni filtros con respecto al For each que los contiene (el del When none | when duplicate).
Son consideradas navegaciones independientes (la del code1, code2 y code3).
182
Los code snippets son plantillas de cdigo que GeneXus tiene predefinidas, que nos ayudan a
escribir el cdigo fuente. Cuando estamos trabajando en el Source de un procedimiento, la Toolbox
nos muestra varios snippets que nos facilitan la escritura del comando For each.
Los snippets tienen a su vez un atajo (shorcut), que hacen que la escritura de cdigo sea ms
rpida todava. Por ejemplo, digitando simplemente fe se escribe automticamente el siguiente
cdigo:
For each
/*For each Code*/
Endfor
Luego el usuario sustituye la lnea de comentarios con el cdigo necesario.
La lista de los atajos de cada snippet, es la siguiente:
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)
183
El For each es un comando como otros, y por tanto puede aparecer varias veces dentro del Source,
tanto en forma paralela (independiente), como anidado a otro For each.
Cuando dentro del cuerpo del For each (code1) aparece otro For each, decimos que se trata de For
eachs anidados. GeneXus soporta varios niveles de anidamiento para los For eachs.
El caso en el que un For each aparece en el bloque de cdigo code3, si bien puede verse como un
anidamiento de For eachs porque uno aparece dentro de otro, el comportamiento en cambio, es
como el del caso de For eachs paralelos.
Un For each anidado en el When none de otro, solo se ejecutar si no existe ningn registro de la
tabla base del For each que lo contiene que cumpla las condiciones de filtro.
En el ejemplo, invoice y bill son dos Printblocks del Layout que continen atributos de las tablas
INVOICE y BILL (recibo) respectivamente.
Hemos definido dos For eachs paralelos. El primero recorrer todas las facturas y el segundo todos
los recibos.
184
El For each es una estructura repetitiva que permite recuperar muchos registros de una tabla. Cuando
uno piensa en For eachs anidados, es evidente que lo que se busca recuperar es, por cada registro del
principal, muchos registros del anidado.
Qu cosas podra GeneXus detectar que se quiere hacer con este tipo de estructuras, de forma tal de
poder inferir el comportamiento automticamente con la menor codificacin posible?
para cada registro de una tabla recuperar algunos de otra: los relacionados.
para cada registro de una tabla recuperar todos los de otra.
procesar informacin por grupos, esto es, agrupar los registros de una tabla segn el valor de un
atributo o conjunto de atributos y para cada grupo, recuperar algunos registros: los correspondientes al
grupo.
Siempre la relacin es uno a muchos: por cada registro de una tabla recuperar muchos de la otra
(pudindose tratar de la misma tabla).
Utilizando esta lgica es que GeneXus infiere las tablas base y el comportamiento de los For eachs
anidados, sabiendo que lo que se desea es implementar alguna de las tres opciones anteriores.
Por ejemplo si queremos realizar un listado de todas las facturas del sistema, donde para cada una
queremos imprimir tambin el detalle de la misma, debemos recorrer dos tablas: INVOICE (que
almacena los cabezales) e INVOICEDETAIL (que almacena las lneas), y lo haremos de una forma bien
simple, sin nombrar las tablas, y sin tener que explicitar todo, como veremos.
Otro ejemplo es el de un listado de todos los clientes, donde para cada uno se quieren imprimir, adems
de sus datos personales, los datos de todas sus facturas. Este comportamiento se logra con un par de
For eachs anidados, donde el primero recorrer la tabla CUSTOMER y el segundo recorrer la tabla
INVOICE, recuperando solo las facturas de ese cliente, como veremos en breve.
185
For each
print invoice_header
For each
print invoice_lines
Endfor
print invoice_amount
Endfor
{InvoiceAmount}
Queremos realizar un listado de todas las facturas del sistema, donde para cada una se muestre
tanto informacin de su cabezal como de sus lneas.
En el Source programado, claramente recorremos la tabla INVOICE, imprimiendo los atributos que
nos interesan del cabezal y para cada registro de esa tabla, recorremos la tabla INVOICEDETAIL,
para imprimir los atributos que nos interesan de sus lneas.
Tan simple como eso! Otra vez, nos alcanza con nombrar los atributos que queremos utilizar y del
resto se encarga GeneXus.
Observemos que ni siquiera tuvimos que especificar condicin de filtro sobre los registros de
INVOICEDETAIL a recuperar. GeneXus se da cuenta de la relacin existente entre las tablas, y aplica
automticamente la condicin de filtro sobre los datos, de manera tal de solo imprimir las lneas de
esa factura (recordar que algo idntico ocurra con las frmulas verticales, como InvoiceAmount,
donde la condicin de filtro sobre los registros a ser sumados o contados quedaba implcita, y no
haba que especificarla).
186
INVOICEDETAIL
Paracadaregistro deINVOICEimprimiralgunosdesusdatos
(InvoiceId,InvoiceDate)ydesuextendida(CustomerName).
LuegonavegarINVOICEDETAILyrecuperarlosregistrosque
correspondanalafacturaqueseest imprimiendo.
Losquecumplanlacondicinimplcita:
INVOICEDETAIL.InvoiceId =INVOICE.InvoiceId
Como para un For each simple, GeneXus debe determinar para cada For each (principal y anidado)
cul es su tabla base. Y luego, a partir de esa determinacin, inferir la lgica correspondiente.
Ms adelante veremos con exactitud cmo es que GeneXus determina cada tabla base. Aqu nos
quedaremos con la idea intuitiva de que lo hace en forma similar a como lo haca para el caso de un
For each simple.
Encuentra, pues, que debe recorrer las tablas INVOICE e INVOICEDETAIL.
Como esas tablas estn relacionadas de acuerdo a una relacin 1-N infiere ms que eso: infiere
adems que debe aplicar la condicin sobre los datos de INVOICEDETAIL que se indica arriba.
187
Cuando tenemos For eachs anidados, GeneXus debe determinar la tabla base de cada uno, y esas
sern las tablas que se navegarn.
Para cada registro de la tabla base del For each principal, se ejecutarn los comandos del cuerpo del
mismo. Entre esos comandos, se encuentra el For each interno, que se ejecutar, como cualquier
otro comando, en el lugar donde se encuentre, realizando una navegacin sobre su tabla base.
Pero para la determinacin de la tabla base del For each anidado, podr influir la tabla base del For
each principal, por lo que las determinaciones no son por completo independientes, como podra
pensarse.
A partir de la determinacin de las tablas base de cada For each primero y de las relaciones que
encuentre GeneXus entre las tablas involucradas luego, surgen tres posibles casos de For eachs
anidados: join, producto cartesiano y corte de control, respectivamente.
Estudiaremos en lo que sigue cada uno de estos casos con ejemplos, para luego generalizar todo lo
visto.
188
For each
...
For each
...
Endfor
...
When none
...
Endfor
189
INVOICE
Para el ejemplo que presentamos antes, mostramos arriba cmo se determina cada tabla base.
Para la del anidado, como los atributos que figuran no estn contenidos en la tabla extendida de
INVOICE (que es la tabla base del principal), entonces se pasa a determinar su tabla base como se
explic anteriormente: se busca la tabla extendida mnima que contenga a ProductDescription,
ProductPriceListPrice, InvoiceDetailQuantity e InvoiceDetailAmount, y que de ser posible est
relacionada con INVOICE.
La tabla que cumple ambos requisitos en INVOICEDETAIL.
190
Fe anidado ?
S
No
Tablasbaseiguales
CortedeControl:Correspondealcasoenelquequeremosrecuperar
(Caso 3)
informacinporgrupos.
De la determinacin de las tablas base, surgen los tres casos de For eachs anidados que se
mencionan y que estudiaremos uno a uno en lo sucesivo.
Este tema es de vital importancia, ya que la mayora de las aplicaciones requieren navegaciones
complejas sobre las tablas, donde se requiere una mixtura de todos estos casos.
191
Caso 1: Join
Distintastablasbaseperoexisteunarelacin1Ndirectao
indirectaentreellas.
Ejemplo:Listadodetodoslosclientesysusfacturas.
For each
print customer
For each
print invoice
Endfor
Endfor
CUSTOMER
{CustomerId,
CustomerName}
{InvoiceId, InvoiceDate,
InvoiceAmount}
CustomerId
INVOICE
Este es el caso en el que GeneXus determina que las tablas base de cada For each son distintas y
hay una especie de relacin 1-N (pudiendo ser sta indirecta, como veremos luego) entre las tablas
que se recorren.
Es decir, por cada registro de la tabla base del For each principal, GeneXus encuentra que hay N
relacionados con l, directa o indirectamente, en la tabla base del For each anidado.
Al encontrar esta relacin, aplicar condiciones de filtro automticas en el For each anidado, de forma
tal de solo quedarse con esos registros relacionados.
El ejemplo del procedimiento en el que se imprimen todas las facturas del sistema, con sus detalles,
cae dentro de esta categora. En ese caso hay una relacin 1-N directa entre las tablas que se
recorren: para cada cabezal de factura, se lista el mismo, junto con todas sus lneas de factura, es
decir, todos los registros de INVOICEDETAIL que estn relacionados con el registro de INVOICE en
el que se est posicionado en cada iteracin.
Este es uno de los casos ms comunes de For eachs anidados, donde se quiere recorrer una tabla, y
para cada registro de la misma, recorrer otra tabla, relacionada con la primera por una relacin N-1.
GeneXus encuentra esta relacin, y en la navegacin interna solo recupera los registros asociados, y
de ah el nombre de join para este caso.
En el ejemplo presentado arriba ocurre lo mismo. La tabla base del primer For each es CUSTOMER,
y la del segundo, INVOICE. Como encuentra atributo en comn entre la tabla extendida del For
each principal y la tabla base del anidado1, CustomerId, determina que ese atributo actuar como
condicin de filtro en la recorrida de la tabla del For each anidado.
--------------------------------------------------------------------------------------------------------------------------------------------------1 Esta es una forma de expresar formalmente lo que habamos dicho en trminos informales: relacin directa o
indirecta 1-N entre las tablas base. La relacin ser directa cuando la tabla base del principal tenga relacin 1-N
con la tabla base del anidado, es decir, sea superordinada de esta ltima. La relacin ser indirecta cuando esto
no exista una relacin directa entre las tablas base, pero s entre la tabla extendida del primero y la tabla base del
segundo. Tambin ser indirecta cuando la tabla extendida del anidado incluya a la tabla base del principal. De
esto veremos ejemplos luego.
192
Caso 1: Join
Veamos, por ahora intuitivamente, cmo hace GeneXus para determinar las tablas base. Los
atributos utilizados en el For each externo son CustomerId y CustomerName, por lo que la tabla base
de este For each ser claramente CUSTOMER. Observemos que solo participan en la determinacin
de esta tabla base los atributos del For each principal, no los del anidado.
Luego GeneXus debe encontrar la tabla base del For each anidado. Los atributos que participan son
InvoiceId, InvoiceDate y InvoiceAmount, es decir, los atributos internos a este For each. Observemos
que estos atributos no pertenecen a la tabla extendida del principal, que era CUSTOMER. Por tanto
se pasa a determinar su tabla base como la de cualquier For each simple: la tabla extendida de
INVOICE contiene a todos los atributos del For each anidado, y es la mnima tabla extendida que los
contiene. Por lo tanto, INVOICE ser elegida como tabla base del segundo For each.
Observemos, nuevamente, que no explicitamos clusula where en el For each anidado para filtrar las
facturas del cliente del For each principal. Justamente, por tratarse de tablas relacionadas por una
relacin 1-N directa, esta condicin es aplicada implcitamente por GeneXus y puede verse
claramente en el listado de navegacin que se muestra arriba.
Hay otro hecho interesante que podemos observar en este listado: si bien en el For each anidado no
especificamos clusula order, GeneXus no eligi el orden por clave primaria de la tabla base sino por
el atributo relacin, CustomerId. De esta manera, est optimizando automticamente la consulta.
Ac se presenta, pues, una excepcin a la regla que enunciaba que cuando no se especifica clusula
order en un For each, GeneXus determina como orden el de la clave primaria de la tabla base de
dicho For each.
193
Caso 1: Join
Ejemplo:Listadodetodaslasfacturasporpas
{CountryId, CountryName}
For each
print country
For each
print invoice
Endfor
Endfor
CountryId
CUSTOMER
COUNTRY
CustomerId
INVOICE
Si queremos realizar un listado de las facturas emitidas por pas, tenemos otro caso de For eachs
anidados con distintas tablas base, donde la informacin que se quiere listar est relacionada.
Aqu queremos recorrer las tablas COUNTRY e INVOICE.
Observemos que si bien no estn relacionadas directamente, s lo estn en forma indirecta. De
hecho, COUNTRY pertenece a la tabla extendida de INVOICE. Por lo tanto, por cada factura se
puede encontrar un solo pas relacionado con la misma.
Hilando fino, este es un caso un poco ms complejo que el anterior, porque si bien la tabla extendida
del For each principal no tiene interseccin con la tabla base del anidado (ext(COUNTRY)
INVOICE = ), sin embargo s existe una relacin 1-N indirecta, y GeneXus la encuentra.
En este caso, la tabla base del For each principal est incluida en la extendida del anidado
(COUNTRY ext(INVOICE)), por lo que hay una relacin 1-N indirecta.
Por este motivo, no necesitamos especificar clusula where en el For each interno para filtrar las
facturas del pas del For each principal.
Esto puede verse claramente en el listado de navegacin, que mostrar el filtro:
CountryId = CountryId para el segundo For each, pero esta vez como Constraint dado que no
puede optimizar la recorrida.
Puede probar el lector este caso en GeneXus y estudiar detenidamente el listado de navegacin
resultante.
194
En este caso GeneXus no logra encontrar una relacin 1-N directa o indirecta entre las tablas y por lo
tanto no aplica filtros implcitos a los registros del For each anidado, vale decir, realiza un producto
cartesiano entre las tablas.
El caso se da cuando:
ext(For each principal) base(For each anidado) = y
base(For each principal) ext(For each anidado)
Para cada registro de la tabla base del For each principal se recorre toda la tabla base del For each
anidado.
Por ejemplo, si la tabla base de un For each fuera COUNTRY y la del anidado PRODUCT,
evidentemente no existir relacin y se har un producto cartesiano y se recorrer para cada pas,
todos los productos.
Por supuesto que el programador podr establecer filtros sobre los datos a recuperar, pero stos ya
no sern condiciones implcitas inferidas por GeneXus, sino especificadas explcitamente por el
programador.
195
En el ejemplo que habamos visto antes, del listado de clientes y sus facturas, qu ocurre si un cliente
no tiene facturas?
Como la tabla base del For each principal es CUSTOMER, el cliente sale impreso antes de saberse si
tiene o no facturas.
Si no deseamos que esto ocurra, es decir, que salgan listados clientes que no tengan facturas,
entonces la solucin es acceder nicamente a las facturas, pues si un cliente est en esta tabla, es
porque est en una factura!.
Pero para poder agrupar las facturas por cliente, de forma tal de poder desplegarlas de ese modo,
debemos recorrer la tabla INVOICE ordenada por CustomerId. De esta forma procesaremos la
informacin de un cliente, y luego pasaremos al siguiente, para procesar su informacin, y as
sucesivamente.
Si imaginamos un puntero que se va desplazando secuencialmente por la tabla INVOICE, podemos
escribir el pseudocdigo de nuestro procedimiento como sigue:
1. Para el registro apuntado, retener el valor del atributo de corte o agrupamiento, CustomerId.
2. Acceder a la tabla CUSTOMER (que est en la extendida de INVOICE) para recuperar el
CustomerName e imprimirlo junto con el CustomerId (print customer)
3. Mientras el valor de CustomerId del registro apuntado coincida con el valor retenido en el paso 1
(aqu se procesan todas las facturas del cliente)
a.
Imprimir InvoiceId, InvoiceDate e InvoiceAmount del registro apuntado.
(print invoice)
b. Avanzar el puntero al siguiente registro y volver al paso 3.
4. Volver al paso 1. (cuando se lleg a este punto, es o bien porque se lleg al fin de tabla o bien se
cambi de cliente).
196
orden determina el
criterio de corte
Cada vez que cambia el cliente se
define un nuevo grupo
GeneXus brinda una forma de implementar lo anterior de una forma absolutamente sencilla.
El pseudocdigo visto en la pgina anterior se implementa en GeneXus con el par de For eachs
anidados que se muestran arriba.
Si se compara este cdigo con el que vimos unas pginas atrs para el caso de join, vemos que
existen solamente dos diferencias: la clusula order que aparece en este cdigo, en conjuncin con el
defined by. Con solo esos dos cambios al listado original, cambiamos radicalmente el comportamiento,
puesto que en este caso solamente se listarn los clientes si tienen facturas.
En este caso, ambas clusulas (order y defined by) son indispensables para que este procedimiento
funcione del modo que queremos. Si agregamos solo una de ellas, pero no la otra, el resultado ser
otro.
No en toda implementacin de un corte de control deber especificarse una clusula defined by en el
For each principal, mas s una clusula order.
La clusula order es indispensable, porque es la que especifica por qu atributo o conjunto de
atributos se realizar el corte (o agrupamiento). Es decir, especifica esa informacin comn al grupo,
que se procesar una sola vez (dentro el cdigo del For each externo).
La clusula defined by no es indispensable en todos lo casos. En este s lo fue, porque de no
especificarla, GeneXus determinara como tabla base del For each principal CUSTOMER, que no es lo
que queremos (pues no queremos implementar un join, cosa que ya hicimos antes, sino un corte de
control, para solo recorrer la tabla INVOICE).
Pero tambin podramos haber utilizado otra solucin para modificar la tabla base del For each
principal: utilizar en vez del defined by el comando print if detail dentro del cuerpo del primer For each
(este comando le dice a GeneXus que tome como tabla base del For each, la que determine para el
anidado).
197
Un corte de control es bien simple de implementar y puede hacerse siguiendo las consideraciones
anteriores.
En el order del For each ms externo, debemos mencionar el primer atributo de corte, en el order
del segundo For each debemos mencionar el segundo atributo de corte, y as sucesivamente. No es
obligacin mencionar atributo/s en el order del For each ms interno (en todos los dems For each s
lo es).
Corresponde al caso en el que nos interesa trabajar con la informacin de una tabla, pero agrupada
por algn atributo o conjunto de atributos.
Los cortes de control pueden ser simples, dobles, triples, etc.
A continuacin veremos un ejemplo de un corte de control doble.
198
Total
20
Total
40
15
Total
20
Como ahora queremos agrupar por cliente, y dentro de ese grupo por fecha de factura, necesitamos tres
For eachs anidados:
For each order CustomerId
defined by InvoiceDate
print customer
For each order InvoiceDate
print date
For each
print invoice
Endfor
Endfor
Endfor
Como ejercicio, sigamos todos los pasos que realiza GeneXus para inferir el comportamiento del
procedimiento.
1. Determinacin de la tabla base de cada For each
Como siempre, para determinar las tablas base de For eachs anidados, se empieza de afuera hacia
adentro, determinando la de cada For each, sin tomar en cuenta los atributos de los For eachs internos
al que se est considerando.
199
2. Determinacin de la navegacin
Luego de determinadas las tablas base, GeneXus determina la navegacin. Como en este caso son tres For eachs
sobre la misma tabla base, se trata de un doble corte de control.
Podemos pensar que cuando hablamos de corte de control, ya sea simple, doble, triple, cudruple, etc., tenemos un
solo puntero, que se utiliza para avanzar en los registros de la tabla base.
Recordemos que la clusula order es fundamental para establecer el criterio de corte en cada par de For eachs.
Como en nuestro caso queremos agrupar por CustomerId y luego, para todas las facturas con ese cliente, agrupar
por InvoiceDate, entonces tendremos que ordenar el primer For each por CustomerId y el inmediatamente anidado
por InvoiceDate.
En el ejemplo estamos diciendo que:
Mientras no se alcance el fin de tabla
Imprimir los datos del cliente de la factura actual
Mientras no cambie el cliente
Imprimir la fecha de la factura actual
Mientras no cambie la fecha
Imprimir los datos de la factura actual (nro y total)
Avanzar el puntero al siguiente registro
200
201
Comandos de control
if cond
bloque1
[else
bloque2]
endif
do while cond
bloque
enddo
do case
case cond1
bloque1
[case cond2
bloque2]
......
[case condn
bloquen]
otherwise
bloquen+1
endcase
Los comandos introducidos son similares a los existentes en los lenguajes de programacin
imperativa conocidos, por lo que no incluimos documentacin de este tema. Puede encontrarla en el
curso no presencial o en el Help de GeneXus. Los dos ltimos, no obstante, incorporan algunos
elementos interesantes sobre el manejo de arrays y de colecciones1 en GeneXus, por lo que
mostraremos algunos ejemplos.
For to step:
inicio, fin son expresiones numricas
salto es una constante numrica
var es alguna variable numrica
bloque es una sucesin de comandos vlidos del lenguaje
Permite iterar una cierta cantidad de veces: desde el valor inicio que toma la variable &var cuando
se ingresa al bucle, hasta el valor fin que tomar la misma luego de cierta cantidad de iteraciones. De
iteracin en iteracin la variable &var se va incrementando automticamente en una cantidad igual a
salto. El valor por defecto de salto es 1, por lo que si no se especifica la clusula step el incremento
de la variable ser de uno en uno. El valor de salto puede ser negativo y en ese caso se ir
decrementando la variable de iteracin en iteracin.
Ejemplo
For &i = 1 to 5
&ok = PInvoicing.udp( &month )
Endfor
-------------------------------------------------------------------------------------------------------------------------------Las colecciones representan listas de largo variable. Se vern cuando estudiemos el tipo de datos estructurado
(SDT).
1
202
For in Expression:
Expression es cualquier expresin cuyo valor sea una coleccin, vector o matriz.
var es una variable que debe tener el mismo tipo de datos que los elementos de Expression.
Esta estructura de programacin permite recorrer con menos cdigo una coleccin o una variable array
de una o ms dimensiones. Se almacena en la variable &var los valores de cada elemento de la
coleccin, array o matriz.
Para el caso de arrays de una dimensin:
for &var in &varArray()
// code
Endfor
el cdigo se expande (es equivalente) a:
&x = 1
do while &x <= rows(&array())
&var = &Array(&x)
bloque
&x += 1
enddo
En el caso de dos dimensiones:
for &var in &varMatrix()
// code
Endfor
el comando se expande (es equivalente) a:
&x = 1
do while &x <= rows( &array() )
&y = 1
do while &y <= cols( &array() )
&var = &array( &x, &y )
bloque
&y += 1
enddo
&x += 1
enddo
Tambin puede ser una variable coleccin de cualquier tipo, incluyendo una variable con la propiedad
Collection en 'False' pero de un tipo de datos 'SDT collection' .
for &var in &collection
...
endfor
La expresin tambin puede no ser una variable, por ejemplo en el caso del resultado de un DataProvider o de un
Procedure:
for &var in DataProvider(parms)
...
Endfor
for &var in Procedure(parms)
...
endfor
Consideraciones:
No es posible modificar los valores de la coleccin, array o matriz en la recorrida. Esto significa que
cambios en el valor de &var en el alcance de la estructura, no afectan al correspondiente valor de la
&collection o del &array(&x), o de &array(&x, &y)).
No es posible obtener la posicin de la coleccin/array/matriz durante la recorrida, para esto es
necesario definir una variable que acte como contador.
Estas estructuras pueden anidarse para recorrer varios arrays, matrices o colecciones. Esto incluye el
caso de que se invoque a una Subrutina que tambin tiene un For In Expression.
Al igual que en un For Each o un Do While, es posible incluir comando que corten la recorrida, como
Exit o Return.
203
Comandos de impresin
Print
SeutilizaparaimprimirenlasalidaunPrintblock definidoenelLayout
Sintaxis:Print nombrePrintBlock
Header
Seutilizaparadefinirloquesequiereimprimircomoencabezadodecadapgina
dellistado
Sintaxis: Header
bloque
end
Footer
Definelaslneasdepiedepginaaserimpresasalfinaldecadapginadel
procedimiento.
Sintaxis: Footer
bloque
end
Aqu veremos algunos comandos de impresin, que permiten disear la salida del procedimiento.
Print
donde nombrePrintBlock es el identificador de un Printblock del Layout. Si no existe en el Layout un
Printblock con ese nombre, al intentar salvar el objeto se desplegar un mensaje de error informando
sobre esta situacin.
De esta forma se implementa la impresin en la salida de los Printblocks del Layout.
Cuando el Printblock que se quiere imprimir no contiene atributos, entonces este comando se puede
utilizar en cualquier lugar del Source.
Los atributos indican acceso a la base de datos y este acceso no puede realizarse en cualquier lado,
sino nicamente dentro del comando especfico para ello, esto es, el comando For each.
Por tanto no es correcto escribir el comando print fuera de un For each si el Printblock que se est
queriendo imprimir contiene atributos.
La nica excepcin a esta regla se produce cuando los atributos del Printblock estn incluidos entre
los parmetros recibidos por el procedimiento, pues en este caso no es necesario acceder a la base
de datos para recuperar sus valores, dado que ya vienen instanciados.
Header
Aqu se define lo que se quiere imprimir como encabezado de cada pgina del listado.
Este encabezado es opcional. Si no se especifica, entonces las pginas del listado no tendrn
encabezado.
204
Ejemplo: En el procedimiento en el que queramos imprimir un listado con el cdigo, nombre y pas de
cada uno de los clientes de nuestro sistema, si queremos que en cada pgina del listado aparezca el
encabezado: CUSTOMERS REPORT, entonces alcanza con escribir en el Source:
Header
Print title
End
Donde title es el nombre de un Printblock del Layout que contiene este texto.
Tambin podramos haber escrito directamente: Print title al comienzo del Source, pero en este caso,
si el listado tiene varias pginas, solo saldr impreso este texto en la primera. En el otro caso, saldr
en cada una de las pginas, como encabezado.
Footer
Define las lneas de pie de pgina a ser impresas al final de cada pgina del procedimiento.
Los comandos del bloque de cdigo son ejecutados cuando se llega al final de una pgina.
Ejemplo:
Footer
print endOfPageText
end
donde endOfPageText es el nombre de un Printblock del Layout
205
Diseo de la salida
Existen algunos comandos para disear la salida del procedimiento. Presentamos aqu algunos a los
efectos de la documentacin.
MT nlines: nlines es el nmero de lnea en el que se quiere empezar a imprimir el listado. En caso de
no especificarse un valor se asume el valor por defecto que es 0.
MB nlines: nlnes es el nmero de lneas que se desea dejar como margen inferior.
En caso de no especificarse un valor se asume el valor por defecto que es 6.
PL nlines: Setea el largo de pgina. El nmero de lneas que ser impreso es el nmero especificado
menos el margen de abajo (valor por defecto es 6). Ej: PL 66
Setea el largo de pgina a 66 lneas, aunque slo 60 lneas sern impresas en el form, con un
margen inferior de 6 lneas.
CP nlines: Si queda en la pgina actual un nmero de lneas mayor o igual al nmero especificado,
contina imprimiendo en la misma pgina. De lo contrario, pasa a imprimir en la prxima pgina
(fuerza a un salto de pgina).
Lineno nline: Define el nmero de lnea donde va a ser impresa la siguiente lnea. Si el nmero de
lnea actual es mayor al nmero especificado, entonces, la lnea ser impresa en la prxima pgina.
El conteo de lneas comienza en la lnea 0.
Eject: Fuerza a un salto de pgina.
Noskip: Tiene que estar inmediatamente despus de un Printblock. Si el comando se encuentra entre
dos lneas, este comando las imprimir en la misma lnea.
206
Procedimientos PDF
Configurarlaspropiedades:
Main Program =True
Call Protocol =HTTP
Report Output=Only to file
Regla
Output_file(xx.pdf,PDF)
En Web los listados solamente pueden ser PDF y se deben configurar las propiedades y regla
anteriores para que funcionen.
207
Condiciones
Permitenespecificarcondicionesglobalesquedeberncumplir
losdatosaserrecuperados.
Ejemplo:
En esta seccin se permiten establecer condiciones que deben cumplir los datos para ser
recuperados.
Una condicin es equivalente a la clusula where del comando For each (incluso tiene la misma
sintaxis) con una salvedad: mientras que la clusula where est ligada a un For each especfico:
aquel al que pertenece, las condiciones estn ligadas a todos los For eachs del Source en los que
tenga sentido aplicarlas.
Y para qu For eachs tiene sentido aplicarlas?
Las condiciones generalmente involucran atributos. Si en la tabla extendida de un For each se
encuentran los atributos que intervienen en una condicin, entonces la misma se aplicar a este For
each para filtrar los datos quedndose nicamente con aquellos que satisfagan tal condicin.
En el listado de navegacin del procedimiento se indican los For eachs a los que se aplica cada
condicin de las especificadas en la seccin Conditions.
Si en el Source del procedimiento PrintCustomers tenemos:
For each
Print customer
Endfor
Entonces al especificar las condiciones que se muestran en la transparencia, estaremos filtrando los
clientes, de acuerdo a las condiciones (es equivalente a tener las condiciones como where).
208
Condiciones
SielSource delprocedimientoes:
For each
Print customer
Endfor
For each
Print invoice
Endfor
For each
Print product
Endfor
For each
where CustomerName>=&start
Print customer
Endfor
For each
where CustomerName>=&start
where InvoiceId < 100
Print invoice
Endfor
For each
Print product
Endfor
donde:
customer es un Printblock que contiene los atributos CustomerId, CustomerName, CountryName
invoice es un Printblock que contiene los atributos InvoiceId, CustomerId, CustomerName,
InvoiceDate, InvoiceAmount
product es un Printblock que contiene los atributos ProductId, ProductDescription, ProductStock
Si el procedimiento anterior tiene definidas las condiciones mostradas arriba, el procedimiento ser
equivalente a uno sin condiciones y con el Source que se muestra a la derecha.
Observemos que en este caso las condiciones se traducen en clusulas where pero que se aplican
solo a los For eachs para los que tiene sentido aplicarlas. En la tabla extendida del ltimo For each no
se trabaja con nombre de cliente, ni con identificador de factura. No tiene sentido aplicar las
condiciones en este For each ya que no existe ninguna relacin.
En el primero, solo tiene sentido aplicar la que involucra a CustomerName y no la otra.
Observacin
Los atributos involucrados en las condiciones no participarn en la determinacin de las tablas base
de los For eachs del Source (a diferencia de los filtros que se especifican mediante clusulas where).
Es decir, las tablas base de los For eachs que aparezcan en el Source se determinan sin mirar las
condiciones. Una vez determinadas, recin en ese momento las condiciones son examinadas para
determinar a cules For eachs se aplicarn y a cules no.
Lo mismo ocurre con los atributos que se reciban como parmetro. Aplicarn como filtro global por
igualdad para los For eachs en los que tenga sentido, pero no participarn en la determinacin de las
tablas base.
209
Filtros en la navegacin
Formas defiltrar losdatos:
Clusulas Where
Condiciones
Resumimos aqu las distintas formas de filtrar en un procedimiento la informacin a recuperar de la base
de datos:
a. clusulas where
b. Condiciones
c. parm( att, ..., att )
Estudiemos las diferencias y similitudes entre ellas.
1. Las clusulas where aplican exclusivamente al For each en el que se encuentran, mientras que los
filtros especificados como condiciones o los que quedan determinados por los atributos en la regla
parm son globales, es decir, aplicarn a todos los For eachs del Source en los que tenga sentido
aplicarlos.
2. Los filtros que quedan determinados al recibir atributos en la regla parm son filtros por igualdad, es
decir, para los For eachs en los que tenga sentido aplicarlos, se instanciarn nicamente los registros
que tengan el mismo valor que el recibido por parmetro. En cambio, los filtros especificados en las
clusulas where de un For each o en las condiciones pueden ser expresiones booleanas cualesquiera,
incluso compuestas.
3. Mientras que los atributos que aparecen en las clusulas where participan en la determinacin de la
tabla base del For each donde se encuentran, los que aparecen en las condiciones o en la regla parm no
lo hacen. Recin entran en juego LUEGO de determinadas las tablas base de los For eachs del Source.
210
211
Por ejemplo:
Procedimiento que imprime clientes activos, agrupados por sexo.
Procedimiento que aplica un descuento, slo para clientes activos.
Web Panel que muestra el total de ventas por cliente, slo de clientes activos.
El atributo CustomerStatus est basado en un dominio enumerado, Status, que tiene 3 valores:
Active
On Hold
Closed
Los clientes activos sern aquellos que tengan el valor Status.Active.
212
Parameters: Parmetros recibidos desde la invocacin del Data Selector, para ser usados en conditions.
Conditions: Condiciones para filtrar los datos a ser recuperados.
Orders: Orders condicionales (cada order con sus atributos separados por coma y when opcional).
Defined by: Atributo o lista de atributos que colaboran en la definicin de la tabla base final.
213
Ejemplo:
Customer
{
CustomerId*
CustomerName
CustomerAddress
CustomerGender
CustomerStatus
}
CustomerStatus=
Status.Active
La forma de referenciar a un Data Selector depender desde cul de los casos se desee invocar. Veremos la
sintaxis para cada caso.
214
Facilitanelmantenimiento:Secambialadefinicin enunnico
lugar yelcambio aplica automticamente atodo lugar delaKB
enelque seutilice.
Optimizanelconocimiento:Facilitanelentrenamientode
personalnuevoparaunproyecto,graciasalencapsulamiento
queproveen.
215
216
Ejemplo 1:
EndFor
For Each USING ActiveCustomers()
EndFor
Ejemplo 2:
EndFor
Esto se
Expande a:
For Each
Where CustomerStatus = Status.Active
Where CountryName = "Uruguay"
EndFor
Clientes activos
de Uruguay
Nota:
La performance ser la misma si se escriben 2 where en el For Each que si se referencia un Data Selector en
el For Each (que tiene definida una condition) + un where en el For Each.
GeneXus siempre tratar de optimizar el cdigo generado, sin embargo no ms por utilizar el concepto de Data
Selectors , ya que su objetivo como venimos explicando, es: centralizar el conocimiento reusable en una sola
definicin y luego referenciar esa definicin en todas las consultas y clculos de la KB que aplique.
Dado que en estos ejemplos presentados, se est referenciando en For Each al Data Selector con clusula
USING, los atributos presentes en la definicin del Data Selector intervienen en la determinacin de la tabla
base del For Each. Por esto, en ambos ejemplos, la tabla base del For each es: CUSTOMER.
217
Sintaxis:
For Each
Where <attribute> IN DataSelectorName([[parm1 [,parm2 [, ..] ])
EndFor
Ejemplo:
For Each
Where CustomerId IN InvoicesByDate(&FromDate, &ToDate)
NO
DE
En este ejemplo:
La tabla base del Data Selector es: INVOICE
El atributo que antecede al operador IN pertenece a la tabla extendida de INVOICE (CustomerId) y la
consulta asociada al Data Selector devolver una lista de valores correspondientes a dicho atributo (devuelve
una lista de clientes que tienen facturas en el rango de fechas dado).
El For Each tiene su tabla base determinada por los atributos incluidos en el For Each y sin tener en cuenta a
la informacin almacenada en el Data Selector.
El For Each navegar su tabla base y extendida, filtrando los registros que contengan a alguno de los clientes
de la lista devuelta por el Data Selector.
218
Es posible utilizar Data Selectors en frmulas Aggregate tanto globales como locales.
Sintaxis: NombreFormulaAggregate '(' <Expresin> ',' [<CondicinAgg>] ',' [<ValorDef>]')'
Find | Max | Min | Sum | Count | Average
Expresin a ser buscada, maximizada, minimizada, sumada o promediada
[<CondicinBsqueda>] ['USING' <DataSelector> '(' <Parmetro1> ',' <Parmetro2> ',' <Parmetro3>')']
Valor a devolver si no hay registros que cumplan con <CondicinAgg>
Ejemplo:
atributo frmula
cant. de clientes
activos del pas
219
220
Frmulas locales
221
Frmulas Locales
Generalidades
Ademsdedefinirfrmulasasociadasaatributos(globales,aniveldelaKB)
tambinesposibledefinirfrmulasenelpropiocdigo.
Llamamosaestecasodeusodelasfrmulas:frmulas inline ofrmulas
locales.
Esposibledefinirfrmulasinline =locales ensource deprocedimientos,
subrutinas,eventos,etc.
Comportamientodependedesisedefinen:
DentrodeFor Each
FueradeFor Each
222
Frmulas Locales
Dentro de For Each
Ejemplo:
Otro ejemplo de codificacin posible es el que sigue, en el cual la frmula se define en el propio where del For
Each, para filtrar por dicho clculo:
For each order CountryId
where Count(CustomerName)>50
Endfor
223
Frmulas Locales
Fuera de For Each
VERSUS
&total=sum(InvoiceAmount)
SUMARIZA FACTURAS
FILTRANDO POR CLIENTE
Solucin:
&CustomerId = 1
do CalcAmount
sub CalcAmount
&total = Sum(InvoiceAmount, CustomerId = &CustomerId)
endsub
Consideracin importante
Una frmula se dispara cuando comienza el grupo que la contiene.
Esto significa que si se tiene definida una frmula con sus parmetros en determinada lnea de cdigo, los
valores de los parmetros van a ser aquellos que fueron ledos cuando el grupo fue ejecutado en la base de
datos. Entonces, si el grupo fue ejecutado en la base de datos, y luego de eso ud. asign valores diferentes a
los parmetros que involucrar en la definicin de la frmula, los valores de los parmetros que se tendrn en
cuenta no sern los que usted asign; por el contrario sern los ledos cuando se ejecut el grupo que contiene
a la frmula en la base de datos.
Y cundo se ejecutan los grupos?
- Cuando comienza un programa.
- Cuando comienza un For Each.
- Luego de un Endfor.
- Cuando comienza una subrutina o un evento.
En particular como en este caso estamos explicando frmulas locales definidas fuera de comandos For
Each, los tems que aplican son 1, 3 y 4.
Lo mismo ocurre con las variables. Los valores de las variables que son tenidos en cuenta al momento de
disparar las frmulas, son los valores que las variables tienen asignados cuando el grupo que contiene a la
frmula se ejecuta. De modo que si escribimos el siguiente cdigo:
&CustomerId = 1
&total = Sum(InvoiceTotal, CustomerId = &CustomerId)
224
sub AmountCalc
do
&total
endsub
AmountCalc
Sum(
InvoiceAmount,
CustomerId
&CustomerId
ya que as logramos un nuevo comienzo de grupo (cuando la subrutina comienza), y en ese momento la
variable ya est cargada con el valor deseado. De modo que con esta solucin, cuando la frmula se ejecute la
variable &CustomerId valdr 1.
225
Tipos de datos
estructurados
SDT
226
SDT: Introduccin
Lenguajesdeprogramacinmanejan:
Tiposdedatossimples (Numeric,Character,etc.)
Tiposdedatoscompuestos.
EjemplodeTiposdedatoscompuestos(registrosotiposde
datosestructurados)
Type Client = Record
Name:
Character(30)
Country: Character(20)
City:
Character(20)
Phones:
Record
Home:
Character(15)
CellPhone: Character(15)
end;
end;
227
SDT en GeneXus
SecreancomocualquierotroobjetoGeneXus.
Editorsimilaraldeestructurasdetransacciones.
SDTsecomponede:miembros,subestructurasycolecciones:
botn
derecho
228
SDT en GeneXus
Ejemploconteniendocoleccin:
Marcando el check box Is Collection se abrir una rama de la estructura como puede verse, donde se le
pedirn dos nombres: el de la coleccin en s, y el de cada tem de la misma.
Como se ver a continuacin, cuando se define una coleccin, junto con el SDT se estar creando
implcitamente otro, que corresponder a los items de la coleccin.
Esto se debe a que de esta forma se podr luego definir una variable del tipo de datos del tem, para
luego agregarla a la coleccin.
229
SDT: Utilizacin
Seutilizanatravsdevariables.
Losatributosno puedenserSDT.
&country
Id
Name
Uruguay
Cities
CityName
Montevideo
CityName
Colonia
CityName
Paysand
A la derecha puede verse el dilogo de propiedades de una variable &country que se est definiendo
dentro de algn objeto.
El SDT Country definido en la KB tal como se aprecia en la pgina anterior, da lugar a la creacin de
dos tipos de datos estructurados: uno correspondiente al propio tipo de datos country y otro
correspondiente a los tems de la coleccin country.City. El por qu de este ltimo caso se debe a que
uno podra querer definir una variable solo de ese tipo de datos, para luego agregarla con el mtodo
Add que ya mencionaremos, a la coleccin.
Obsrvese que la variable &country se ha definido del tipo de datos country que aparece en la lista
obtenida al hacer clic en el combo box de la propiedad Data Type del dilogo de definicin de
propiedades de la variable.
230
SDT: Utilizacin
Paradatosnorepetitivos,seaccedeacadamiembromediante
elnombre,comopropiedaddelavariable.
Name
JuliaJames
Country
Uruguay
City
Montevideo
Phones
Home
555155.55.44
CellPhone
092155.12.33
231
SDT: Utilizacin
Ejemplo:Transaccinqueregistralosrecibosefectuadosalosclientesy
SDTbasadoenlatransaccin:
drag
&
drop
Aqu se presenta un ejemplo con el que continuaremos trabajando en lo que sigue. Agregamos a
nuestra realidad una transaccin de recibos. Supongamos que una vez al mes, se lanza un proceso de
generacin de recibos, en el que, tras elegir un perodo de facturacin (usualmente todo el mes anterior)
para cada cliente se sumarizan todos los montos de las facturas que se le efectuaron en dicho perodo,
y se le genera un recibo (autonumber). La generacin del recibo ser automtica (la realizar nuestro
sistema); ese es un tema que veremos en breve.
Por ahora, supongamos que necesitamos un procedimiento que devuelva los datos de un recibo
determinado de los generados automticamente como explicamos recientemente (por ejemplo, el de id.
7). Una opcin es acceder mediante un for each a la tabla BILL creada a partir de la transaccin de igual
nombre, y junto con la regla parm:
parm( out: BillDate, out: CustomerId, out: CustomerName, out: BillInvoicePeriodStartDate, out:
BillInvoicePeriodEndDate, out: BillAmount);
implementar lo pedido.
La otra opcin, es devolver toda esa informacin en una sola variable estructurada!
parm( out: &bill);
cargada como se muestra arriba. Para ello se define un SDT basado en la transaccin Bill (los SDTs no
pueden tener el mismo nombre que una transaccin, razn por la cul le llamamos BILL_SDT). Para no
tener que ingresar uno a uno los miembros del SDT de igual nombre que los atributos de la transaccin,
alcanza con arrastrar la transaccin Bill desde el Folder View, dentro de la estructura del SDT y
automticamente se inicializar como se muestra arriba.
232
SDT: Utilizacin
Ysiqueremosdevolverunalistaderecibos?
Opcin1:nomodificarelSDTyagregarvariable&bills coleccin:
endfor
Supongamos que queremos devolver una lista de recibos (por ejemplo, los que se hayan efectuado en
un rango de fechas dado).
233
SDT: Utilizacin
&bills
add
&bill.BillDate= BillDate
&bill.CustomerId = ...
&bill.CustomerName = ...
&bill.BillInvoicePeriodStartDate = ...
&bill.BillInvoicePeriodEndDate = ...
&bill.BillAmount = ...
&bills.Add( &bill )
&bill = new Bill_SDT()
&bill
new
Hay que pedir nuevo espacio de memoria para la variable &bill, para la siguiente iteracin.
Como veremos en breve, existe un modo mucho ms sencillo, de ms alto nivel, DECLARATIVO, de
obtener la coleccin de SDTs cargada, sin tener que preocuparnos de realizar operaciones de bajo
nivel, como agregar una variable a la coleccin y pedir memoria...
234
Bills
{
Bill where ...
{
BillDate= BillDate
CustomerId = CustomerId
CustomerName = CustomerName
BillInvoicePeriodStartDate = BillInvoicePeriodStartDate
BillInvoicePeriodEndDate = BillInvoicePeriodEndDate
BillAmount = BillAmount
}
}
...este modo declarativo, por tanto de alto nivel, de cargar una coleccin de SDTs se conoce con el
nombre de Data Provider. Podemos pensarlo como un procedimiento especializado, que devolver
siempre informacin estructurada (ya sea simple como coleccin).
Aqu presentamos el ejemplo, que luego ampliaremos cuando entremos de lleno en este tema.
235
SDT: Utilizacin
Opcin2:modificarelSDTparaqueseacoleccinyluego
trabajardelamismaforma,definiendolasvariables:
&bills
&bill
236
SDT: Utilizacin
Paradatosrepetitivos,seaccedeacadaitemmediantecomando:
For &var in expression
code
endfor
&var:
variable de tipo de datos A
expression: expresin cuyo tipo de datos
es coleccin de A, o array
de A
Ejemplo: A = SDT
237
SDT: propiedades
Los nombres de los miembros de una variable SDT se muestran como
propiedades:
Adems,
para
variables
collection:
&cVar.Count
Retornalacantidaddeitemsdelacoleccin.
&cVar.CurrentItem
CuandounavariableSDTcollectionsedespliegaenunform
(comogrid)permiteseleccionareltemquesehaseleccionado
conelmousecomolneadelgrid.
Las propiedades Count y CurrentItem solo estn disponibles para variables SDT Collection.
238
RetornaunanuevareferenciaopunteroalSDTespecificado
&cVar.Add(&item [, Position])
Agregatemacoleccinenlaposicinrelativaespecificada.Si
seomiteseagregaalfinal.Positioncomienzaen1.
&cVar.Clear()
Eliminatodoslostemsdelacoleccin
&var.Clone()
Creaunanuevareadememoriaycopialosdatosdela
variableenesta: &var1 = &var2.Clone()
&var.FromXML( &xml )
CargavariableSDTapartirdestringconteniendouna
estructuraxml.
&cVar.Item( Position )
RetornareferenciaalelementoconposicinrelativaPosition
enlacollection.
&cVar.Remove( Position)
Eliminatemqueseencuentreenlaposicinespecificaday
correunlugartodaslasposiciones.
&cVar.Sort( memberName)
Ordenaloselementosdelacoleccindeacuerdoamiembro.
&var.ToXml()
RetornaunstringconelformatoXMLdelosdatosdela
variableSDT(quepuedesercollection):ml = &var.ToXml()
Aqu se presentan la mayora de los mtodos con los que cuentan los tipos de datos estructurados.
Algunos aplican a variables SDT no coleccin, se representan con &var, otros a colecciones, se
representan con &cVar.
Para la lista completa, as como ejemplos, acceder al wiki o al help de la versin.
239
SDT: Ejemplo
MtodoToXml:
&xml = &client.ToXml()
Name
JuliaJames
Country
Uruguay
City
Montevideo
Phones
Home
555155.55.44
CellPhone
092155.12.33
<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>
240
Puede seleccionarse del SDT los miembros que quieren cargarse como columnas del grid. Obsrvese
que en nuestro caso hemos omitido los miembros CustomerId, BillInvoicePeriodStartDate y
BillInvoicePeriodEndDate.
241
242
DP: Escenario
Intercambiodeinformacinjerrquicaentreaplicaciones,o
dentrodeunamismaaplicacin.
APPLICATION A
Sistema
de
Facturacin
Data
Interchange
APPLICATION B
2516
John Drotts
12/12/2008
1000
Sistema
de
Deudores/Acreedores
Bill
Id:
Customer:
Date:
Amount:
158
Dane Smith
12/12/2008
750
...
Supongamos que desde nuestro Billing System, queremos enviar a un sistema de deudores y acreedores, un
listado de los recibos correspondientes a cierto perodo de facturacin (es decir, para un perodo determinado
se desea sumarizar para cada cliente el importe total que se le ha facturado y generarle un recibo).
Se trata de informacin jerrquica (enviaremos info de recibos, cada uno de los cules tiene determinados
datos).
El formato ms usual de intercambio de informacin jerrquica suele ser Xml, aunque no sabemos qu
deparar el futuro en ese aspecto (por ejemplo se est volviendo comn el formato Json).
243
Procedimientos procedurales
Cmoobtenemoslosrecibosparaunrangodefechasdado?
Utilizando un procedimiento que reciba el rango de
fechas de facturacin: &start y &end
y devuelva una coleccin de recibos: Bill?
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 and
InvoicePendingFlag )
&bills.Add( &bill )
&bill = new Bill ()
...
endfor
Teniendo el mismo SDT Bill que definimos cuando estudiamos los tipos de datos estructurados (all le
llamamos Bill_SDT, aqu le llamaremos Bill), estamos utilizando un procedimiento con los siguientes
parmetros:
parm( in: &start, in: &end, out: &bills );
siendo &start y &end variables de tipo Date que reciben el rango de facturacin, y &bills una variable collection
del SDT Bill.
Obsrvese que estamos utilizando el Data Selector ActiveCustomers para filtrar por clientes activos y utilizando
la frmula inline sum, en la que nicamente sumamos los totales de aquellas facturas que pertenezcan al
cliente de la actual iteracin del For each y cuyas fechas se encuentren en el rango dado y tengan el valor True
en el atributo Booleano InvoicePendingFlag.
Este atributo ser cambiado a False una vez que la factura haya sido procesada dentro del proceso de
generacin de recibos que iniciamos aqu pero que completaremos ms adelante, cuando estudiemos las
formas de actualizar la informacin de la base de datos (aqu solamente estamos obteniendo la informacin de
los recibos, pero an no los registraremos en la base de datos... ).
244
Procedimientos procedurales
Lenguaje de Input
Lenguaje de Transformacin
Lenguaje de Output
INPUT
Transformation
OUTPUT
Ejemplo:
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
embebido
dentro del
cdigo
?
La intencin
del
procedimiento?
245
Procedimientos declarativos
Lenguaje de Input
Lenguaje de Transformacin
Lenguaje de Output
FORMAT
Transformation
INPUT
Data Provider
OUTPUT
hierarchical structure
TXT
HTML
XML
JSON
SDT
...
Intencin clara
Bills
Bill
BillDate:
12/12/08
CustomerName: John Drotts
...
BillAmount
1000
Bill
BillDate:
12/12/08
CustomerName: Dane Smith
...
BillAmount:
750
...
Con un Data Provider, el foco est ubicado en el lenguaje de salida: obsrvese que se indica en una
estructura jerrquica de qu se compone ese Output.
Luego, para cada elemento de la estructura jerrquica, habr que indicar en el Source del Data Provider, cmo
se calcula.
Por tanto, alcanza con observar el lado izquierdo para deducir cul ser la estructura resultante.
Luego, alcanzar con indicar el formato deseado para esa estructura jerrquica resultante...
246
Procedimientos declarativos
Lenguaje de Input
Lenguaje de Transformacin
Lenguaje de Output
FORMAT
Transformation
INPUT
Data Provider
TXT
HTML
XML
JSON
SDT
...
OUTPUT
hierarchical structure
Bills
Bill
BillDate:
12/12/08
CustomerName: John Drotts
...
BillAmount: 1000
Bill
BillDate:
12/12/08
CustomerName: Dane Smith
...
BillAmount: 750
...
<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
BillDate
12/12/08
CustomerName
John Drotts
...
...
BillAmount
1000
Bill
Bills
BillDate
12/12/08
CustomerName
Dane Smith
...
...
BillAmount
750
Luego, una misma informacin estructurada, podr representarse utilizando los diferentes formatos existentes.
Esa es la idea del Data Provider. Si en el futuro aparece un nuevo formato de representacin de informacin
estructurada, el Data Provider continuar invariable... GeneXus implementar el mtodo de transformacin a
ese formato, y solo habr que utilizarlo.
247
Data Providers
Estructuras jerrquicas
en GeneXus?
SDTs
Bill
OUTPUT
BillDate
12/12/08
CustomerName
John Drotts
...
...
BillAmount
1000
Bill
INPUT
DB
CustomerId
CustomerName
12/12/08
CustomerName
Dane Smith
...
...
BillAmount
750
CustomerStatus
1542
John Drotts
1543
Dane Smith
...
...
...
BillDate
invoices...
Hasta aqu hicimos un anlisis descriptivo. Surge inmediatamente la siguiente pregunta: cmo se representan
en GeneXus las estructuras jerrquicas de datos?
Por tanto, la salida de un Data Provider ser un SDT (o una coleccin de SDTs).
Luego, con esa salida puede realizarse lo que se desee, en particular, convertirla a formato XML, con el
mtodo toXml de los SDTs.
Veamos cmo declaramos la salida... no ser de la forma convencional (como parmetro de out de la regla
parm)...
248
Data Providers
Bill
BillDate
12/12/08
CustomerName
John Drotts
...
...
BillAmount
1000
Bill
BillDate
12/12/08
CustomerName
Dane Smith
...
...
BillAmount
750
OUTPUT
Aqu vemos para el ejemplo que venimos estudiando, que teniendo el SDT definido Bills, collection, que
coincide con la estructura que se infiere del Source del Data Provider GetBills, habr que declarar ese SDT en
la propiedad Output del Data Provider.
Pero no es la nica posibilidad... veremos otra en la pgina siguiente, donde cobrar sentido la propiedad
Collection.
249
Data Providers
Otra posibilidad (mismo resultado):
Bill
BillDate
12/12/08
CustomerName
John Drotts
...
...
BillAmount
1000
Bill
BillDate
12/12/08
CustomerName
Dane Smith
...
...
BillAmount
750
OUTPUT
Si en lugar de tener el SDT collection Bills, tuviramos el que aparece arriba, Bill, entonces podramos
programar el Source del Data Provider como vemos y luego configurar la propiedad Collection en True, con lo
cul se abrir una nueva propiedad, Collection Name, que permitir dar nombre a la coleccin.
Este Data Provider es equivalente al anterior.
Obsrvese que en este caso no es necesario poner la raz de la jerarqua, Bills, puesto que se infiere de la
propiedad Collection Name. De todas formas, si bien no es requerido, podra programarse el Source
exactamente igual al anterior, es decir, con el grupo Bills encabezando la jerarqua.
Bills
{
Bill using ActiveCustomers()
{
...
}
}
Nota: la clusula using, as como las where que veremos luego, order, etc., podrn especificarse tanto a nivel
del grupo Bills, como del grupo Bill, en casos como este. Volveremos sobre este tema ms adelante.
250
Data Provider
Objetivo:Retornodedatosestructurados.
Con Procedimiento: hay que armar el SDT con operaciones
debajonivel.
Con Data Provider: facilidad de escritura y claridad. Es
declarativo independientedeimplementacin.
paradevolverdatosestructuradosutilizaremosunDPen
lugardeunProcedimiento.
Los Data Providers atacan eficientemente un tipo de problema: aquel que consiste en retornar datos
estructurados. Para ese tipo de problemas contbamos con los procedimientos, pero su desventaja evidente
era que necesitbamos implementar la forma de armar esas estructuras con operaciones de bajo nivel, como
agregar un tem a una coleccin con Add, y pedir memoria (new). Asimismo, si hubiera que hacer clculos
complejos para dar valor a cada miembro de la estructura, quedaran en el cdigo embebidos los elementos de
la salida, sin que fuera sencillo visualizar en un golpe de vista la salida resultante del Procedimiento.
Todos estos inconvenientes se evitan con un Data Provider. Aqu el foco est puesto en la salida, razn por la
cul con un solo vistazo quedar evidenciada la estructura del Output. Por otro lado, siendo absolutamente
declarativo, nos independizamos de la forma en que se implementa realmente la carga del SDT. De eso se
encarga GeneXus.
Cuanto ms declarativa sea una herramienta, ms fcil de programar, ms adaptable al cambio, ms
independiente de una implementacin particular. GeneXus tiende a permitir declarar lo ms posible y cada vez
programar proceduralmente menos. Lo declarativo traslada el problema de la implementacin a la
herramienta, y se la quita al programador. Cuanto ms inteligente una herramienta, menos necesidad tendr el
programador de resolver el problema: le alcanzar con enunciarlo.
251
Data Provider
Utilizacin
Objeto GeneXus
&TheBills = GetBills( par1, ..., parn)
udp
Objeto GeneXus
&TheBills = GetBills( par1, ..., parn)
&xml = &TheBills.ToXml()
Un Data Provider tambin puede recibir parmetros va regla parm, pero a diferencia de un procedimiento
donde todos los parmetros pueden ser de entrada/salida, aqu solo podrn ser de entrada.
Por otro lado, un procedimiento que devuelve informacin estructurada lo hace mediante una variable que se
carga en el cdigo, y que debe declararse como de salida, en el ltimo parmetro de la regla parm.
En un Data Provider, la declaracin del tipo de datos de salida se hace mediante las propiedades Output, no
en la regla parm.
La invocacin desde cualquier objeto GeneXus de un Data Provider es idntica a la invocacin de un
procedimiento, es decir, con udp.
Recuerde que al invocar a un objeto y no especificar el mtodo de invocacin, se asume udp.
La variable &TheBills deber estar declarada en el objeto GeneXus en el que se realiza la invocacin. Es la
variable en la que se devolver el resultado. Recuerde que si el SDT definido en la KB es el correspondiente a
los tems individuales: Bill, (y no a la coleccin Bills), entonces la variable &TheBills se definir como
Collection, de tipo de datos Bill.
Luego, con la estructura jerrquica devuelta se podr, por ejemplo, convertir al formato deseado, como XML.
Importante:
Como veremos, un Data Provider no solo puede retornar un SDT o coleccin de SDT, sino tambin otro tipo, el
Business Component, que tambin representa informacin estructurada. Vea ese tema para completar el
conocimiento de Data Providers.
252
Lenguaje de DP
Componentesbsicos:
Grupos
Elementos
Variables
BillsInfo
{
Bills
{
Bill
{
BillDate = &today
CustomerName = CustomerName
BillInvoicePeriodStartDate = &start
BillInvoicePeriodEndDate = &end
BillAmount = sum( InvoiceAmount, ... )
&quantity = &quantity + 1
}
}
BillQuantity = &quantity
}
El ejemplo que podemos ver aqu es parecido al que estuvimos trabajando. Hemos agregado el elemento
BillQuantity. Tmese unos instantes para pensar cmo deber ser el SDT BillsInfo, para que matchee con este
Source. A la izquierda lo hemos presentado.
De todos modos, el Source no tiene por qu escribirse tal cual la estructura del SDT. Cuando en el SDT
tenemos un miembro collection de un determinado tem, podemos omitir del Source el Item como grupo.
Ejemplo: con el SDT que tenemos arriba, podramos haber escrito el Data Provider:
Billsnfo
{
Bills
{
BillDate = &today
CustomerName = CustomerName
BillInvoicePeriodStartDate = &start
BillInvoicePeriodEndDate = &end
BillAmount = sum (InvoiceAmount, ... )
&quantity = &quantity + 1
}
BillQuantity = &quantity
}
con el mismo resultado. GeneXus tiene la inteligencia suficiente como para matchear con el SDT.
253
Lenguaje de DP
Grupos
}
}
BillQuantity = &quantity
}
BillsInfo
{
Bills
{
Bill
{
BillDate = &today
CustomerName = CustomerName
...
&quantity = &quantity +1
}
}
BillQuantity = &quantity
}
254
Lenguaje de DP
Grupos
Ungruporepetitivoesanlogoaunfor each:
Determinatablabase(deigualformaqueenunfor each)
Tienedisponibleslasmismasclusulasqueparaunfor each:
BillsInfo
{
Bills
{
Bill
{
BillDate = &today
CustomerName = CustomerName
BillInvoicePeriodStartDate = &start
BillInvoicePeriodEndDate = &end
BillAmount = sum( InvoiceAmount, ...)
&quantity = &quantity + 1
}
}
BillQuantity = &quantity
&quantity = 0
}
En el ejemplo, el grupo de nombre Bill ser repetitivo. Por qu? Para contestar la pregunta, hagamos otra: y si
fuera un for each, donde los elementos de la izquierda de las asignaciones corresponden a los distintos
elementos de una variable SDT? En este caso la presencia de CustomerName (a la derecha de la segunda
asignacin) permite afirmar que hay tabla base: CUSTOMER.
Por tanto el grupo ser repetitivo, iterando sobre la tabla CUSTOMER.
En el ejemplo que venamos trabajando, podamos tener la clusula:
Bill using ActiveCustomers()
que es como tener:
For each using ActiveCustomers()
por lo que as no estuviera el atributo CustomerName en la segunda asignacin, de todos modos sera con tabla
base, por la presencia del atributo CustomerStatus en el Data Selector ActiveCustomers.
Obsrvese que el grupo de nombre BillsInfo, en cambio, no ser repetitivo, no tiene clusulas asociadas, y los
elementos que contiene estn definidos a base de variables y no de atributos:
BillQuantity = &quantity
&quantity = 0
Y qu pasa con el grupo Bills? Obsrvese que en este caso, es un grupo que slo contiene otro grupo. El grupo
contenido ser repetitivo, por lo que Bills ser una coleccin de Bill. Por este motivo, el subgrupo Bill podra
omitirse (solamente dejar Bills) y que quede implcito. De este modo, las clusulas del grupo que permiten definir
order, filtros, defined by, se pueden asociar a este grupo.
255
Lenguaje de DP
Grupos
Tambinpuedenrepetirsegrupos:
Clients
{
Client
{
Name = Lou Reed
Country = United States
City = New York
}
Client where CountryName = Mexico
{
Name = CustomerName
Country = CountryName
City = CityName
}
}
Si la condicin se hubiese colocado en el grupo Clients, aplicara a los dos subgrupos Client. Por eso es que se
permite que las clusulas operen a nivel de los grupos que se repiten (items), y no solo a nivel del grupo que es
coleccin de tems.
256
Lenguaje de DP
Elementos
UnElementoesunvaloratmicoenelOutput.
CadaElementodebeserasignadoysusintaxisesladelas
frmulas.
Ejemplo:
Clients
{
Client
{
Name = CustomerName
Active = True if CustomerStatus = Status.Active; False otherwise;
}
}
257
Lenguaje de DP
Elementos
ElementosyAtributosusualmentetienenelmismonombre
notacinmscompacta:
Ejemplo:
BillsInfo
{
Bills
{
Bill
{
BillDate = &today
CustomerName = CustomerName
BillInvoicePeriodStartDate = &start
...
}
}
}
BillsInfo
{
Bills
{
Bill
{
BillDate = &today
CustomerName
BillInvoicePeriodStartDate = &start
...
}
}
}
258
Lenguaje de DP
Variables
Algunasvecesesnecesariorealizarclculosinternos:
Ejemplo:
BillsInfo
{
Bills
{
&quantity = 0
Bill
{
BillDate = &today
CustomerName
BillInvoicePeriodStartDate = &start
BillInvoicePeriodEndDate = &end
BillAmount = sum( InvoiceAmount, ... )
&quantity = &quantity + 1
}
}
BillQuantity = &quantity
}
259
Lenguaje de DP
ClusulasdePaginado:Count ySkip
Paramanejarcuntosregistrosirnalasalida.
ClusulaNoOutput
enunGruposignificaqueelgruponodeber estarpresenteenlasalida,sinosolo
suselementossubordinados.
ClusulaOutputIfDetail
Paragrupocabezalconteniendogrupoconsuslneas:solosepresentaelprimeroen
lasalidasitienelneas.
ClusulaInput
sisenecesitatrabajarconcolecciones(devueltasporProcedimientooDataProvider)
comoInput delDP.
http://wiki.gxtechnical.com/commwiki/servlet/hwiki?Data+Provider+Language
Podr encontrar la informacin completa de este tema en ingls en nuestro community wiki, en la siguiente
pgina:
http://wiki.gxtechnical.com/commwiki/servlet/hwiki?Data+Provider+Language
260
Lenguaje de DP
Tabla TAXES
TaxInitialDate*
TaxFinalDate*
TaxVAT
TaxIncome
261
Lenguaje de DP
Customers
{
Customer [Count = 20] [Skip = 100]
{
Code = CustomerId
Name = CustomerName
}
}
262
Lenguaje de DP
Employees
{
Employee
{
Id = EmployeeId
Name = EmployeeName
EarningInfo [NoOutput]
Where IsAutorized(&UserId)
{
Salary = EmployeeSalary
Bonus = EmployeeBonus
}
}
}
<Employees>
<Employee>
<Id>123</Id>
<Name>John Doe</Name>
<Salary>30000</Salary>
<Bonus>5000</Bonus>
</Employee>
...
</Employees>
<Employees>
<Employee>
<Id>123</Id>
<Name>John Doe</Name>
<EarningInfo>
<Salary>30000</Salary>
<Bonus>5000</Bonus>
</EarningInfo>
</Employee>
...
</Employees>
en lugar de
263
Lenguaje de DP
No lo hemos mencionado, pero como intuitivamente podemos pensar, de tener un par de grupos anidados
(un grupo que, entre otras cosas, contiene a otro), si cada uno debe acceder a la base de datos, entonces las
tablas base, as como el criterio de navegacin se determinan exactamente igual que en el caso de un par de
for eachs anidados.
Por ese motivo, en el ejemplo, el grupo Country tiene tabla base COUNTRY; el grupo Customers tiene tabla
base CUSTOMER, y se har un join entre ambas tablas a la hora de recuperar la informacin para cargar la
coleccin de pases. Es decir, por cada registro de COUNTRY se cargar la informacin de sus atributos
CountryId y CountryName en los elementos Id y Name del tem Country del SDT coleccin Countries que se
est cargando, y luego se recorrer la tabla CUSTOMER filtrando por aquellos registros para los cuales
CUSTOMER.CountryId = COUNTRY.CountryId, cargando para cada uno los elementos Id y Name.
La presencia de la clusula OutputIfDetail hace que solamente se presenten en la salida aquellos pases que
cuenten con clientes asociados. Si un pas de la base de datos no tiene cliente alguno, entonces no se
presentar como item de la coleccin de salida, Countries.
264
Lenguaje de DP
Clusula Input
265
Lenguaje de DP
Clusula Input
Paratrabajarconcolecciones.
VerySimple
{
Month Input &i = 1 to 12
{
MonthNumber = &i
}
}
CustomersFromAnotherDataProvider
{
&CustomersSDT = GetCustomers() // a DataProvider that Outputs Customers collection
Customer Input &Customer in &CustomersSDT
{
Id = &Customer.Code
Similar al For &var in Expression
Name = &Customer.Name
del lenguaje procedural
}
}
266
Actualizacin de la Base
de Datos
267
Actualizacin BD
Insert-Update-Delete
Actualizacin interactiva:
Transacciones:
Atravs delformelusuario ingresa/modifica/elimina losdatos.
Ventajas:
Seejecutan las reglas delnegocio (ynoseactualiza registro que viole
regla Errorespecificada)
Noseactualiza registro que viole integridad referencial.
BusinessComponents(BC)
Actualizacin nointeractiva:
BusinessComponents(BC)
Procedures
Hasta aqu slo conocemos una forma de actualizar la base de datos de nuestra aplicacin: las
transacciones.
Como sabemos, una transaccin determina la o las tablas requeridas para almacenar su informacin. A
su vez, al ser generada, se convertir en un programa que implementa la lgica de insercin,
eliminacin y modificacin de datos en esas tablas, en forma totalmente transparente para el
programador. Tambin la transaccin permite definir todas las reglas de negocio que debern cumplir
los datos asociados. El programa generado se encarga de ejecutarlas. As, si en una transaccin
tenemos una o varias reglas Error, que se disparan al satisfacerse determinadas condiciones, esas
reglas estarn incluidas en el cdigo generado, y no se permitir actualizar la base de datos hasta tanto
las condiciones que disparan esas reglas dejen de satisfacerse para los datos que se estn manejando
en esa oportunidad.
Asimismo, como vimos, las transacciones aseguran el control de integridad referencial, muy importante
para asegurar la consistencia de la base de datos.
Pero las transacciones no cubren todas las necesidades en cuanto a la actualizacin de datos. Tambin
se necesitar una forma no interactiva, batch, de realizar actualizaciones sobre tablas.
Para ello existen dos alternativas: actualizacin utilizando lo que se conoce como Business Component,
absolutamente relacionado con las transacciones, o utilizar comandos especficos para tal fin dentro de
objetos de tipo Procedure.
Luego veremos que los Business Components permiten gran flexibilidad, dado que permiten actualizar
la base de datos de cualquier forma: tanto interactiva como no interactivamente.
En lo que sigue introduciremos los Business Components y luego los comandos de actualizacin directa
dentro de Procedimientos.
268
Business Components
Escenario
Necesitamosregistrarlosrecibosqueefectuamosanuestros
clientes.
autonumber
Rules:
Default( BillDate, &today);
Error( The invoice period considered must be past ) if
BillInvoicePeriodEndDate > BillDate;
Error( Wrong invoice period ) if
BillInvoicePeriodStartDate > BillInvoicePeriodEndDate;
269
Business Components
Escenario
BillDate = &today
Collection: True
CustomerId
Collection Name: Bills
BillInvoicePeriodStartDate = &start
BillInvoicePeriodEndDate = &end
BillAmount = sum( InvoiceAmount, InvoiceDate >= &start and InvoiceDate <= &end and
InvoicePendingFlag )
}
270
Business Components
Escenario
...ysipudiramosguardarenunaestructuralosdatosyluego
grabarlosenlabasededatos?
For &bill in GetBills( &start, &end )
&bill.Save()
endfor
Bill
BillDate
12/12/08
CustomerId
2516
...
...
BillAmount
1000
Bill
Bills
BillDate
12/12/08
CustomerId
158
...
...
BillAmount
750
271
Business Components
BC
Por defecto la propiedad Business Component estar apagada. Eso significar que la lgica de negocio
dada por la transaccin, solo se utilizar dentro de la propia transaccin, y no se crear un tipo de datos
de igual nombre que la transaccin, Bill, que permita encapsular la lgica de la transaccin para
utilizarla desde otros objetos.
272
Business Components
En cualquier objeto GeneXus (ej: un procedimiento):
La variable &bill tendr la
misma estructura que el
SDT obtenido a partir de la
transaccin, y se trabaja de
forma anloga, pero adems
ofrecer mtodos para
actualizar la base de datos
en funcin de esos valores.
&bill.BillInvoicePeriodStartDate = #10-10-08#
&bill.BillInvoicePeriodEndDate = #09-10-08#
&bill.Save()
Obsrvese que en este caso la fecha inicial corresponde al da 10 de octubre, mientras la fecha final
corresponde al da 9 de octubre... es decir, la fecha inicial ser posterior a la fecha final...
273
Business Components
Insert
&bill.CustomerId = 3456
&bill.BillInvoicePeriodStartDate = #10-10-08#
&bill.BillInvoicePeriodEndDate = #09-10-08#
&bill.Save()
No se insertar!
10/10/08
>
09/10/08
Obsrvese que se llenan algunos miembros de la estructura de la variable &bill, Business Component, y
luego se ejecuta el mtodo Save (inexistente en SDTs).
Esto es equivalente a lo que en forma interactiva ocurrira si el usuario final ingresa esos mismos
valores en los atributos correspondientes del form de la transaccin, y luego presionara el botn
Confirm.
Por tanto, al igual que como ocurre con la transaccin, debern dispararse las reglas y realizarse los
controles de integridad referencial. Qu pasar con ese juego de datos si se intenta grabar mediante la
transaccin? Se impedir la grabacin, debido a que se est cumpliendo la condicin de la segunda
regla de error (tambin podra cumplirse la de la primera si la fecha de hoy fuera anterior al 10 de
setiembre de 2008). Por otro lado, si no existiera en la tabla CUSTOMER un cliente con identificador
3456, fallar la integridad referencial y as tampoco se dejara ingresar el registro en la tabla BILL de
base de datos.
274
Business Components
Insert
y CustomerName?
Antes de ejecutar el mtodo Save del Business Component, el valor de BillId en la estructura de &bill
ser vaco. Sin embargo, una vez que se ejecute el Save, como el atributo BillId era autonumber en la
tabla BILL, se ejecutar la propiedad a nivel de la tabla y el registro se insertar con el nmero siguiente
al ltimo dado.
En el caso de BillDate, anlogamente, como no se le asigna valor en la estructura de &bill, antes del
Save estar vaco, pero cuando ste se ejecute, se disparar la lgica de la transaccin, y en particular
la regla Default( BillDate, &today ) declarada. Por tanto en el registro insertado en la base de datos, el
valor del atributo BillDate corresponder a la fecha de hoy.
Para BillAmount podramos hacer el mismo anlisis. Pero a diferencia del caso anterior, no hay regla
que le asigne valor, por lo cul se insertar el registro con valor vaco en este atributo.
De asignarse valor para &bill.CustomerName no ser considerado a la hora de la insercin, dado que
CustomerName es un atributo inferido, y no tiene regla Update que permita modificarlo.
Lo mismo sucedera para atributos definidos a nivel de la estructura de la transaccin pero que fueran
frmulas. Es decir, son atributos virtuales en la transaccin, por lo que tambin lo son a nivel del
Business Component. Se disparar su valor.
275
Business Components
Update-Delete
&bill.Load( 100 )
&bill.Delete()
Se realizar siempre y cuando no exista ninguna tabla que referencie al Bill 100!
276
Business Components
Manejo de errores
Booleanos:
&bill.Fail()
&bill.Success()
de tipo
predefinido SDT...
enum
Warning
Error
Para manejar los errores habr que definir una variable de tipo de datos SDT predefinido (viene con la KB)
Messages (collection).
Cuando se ejecutan los mtodos: Save, Check, Load, Delete se disparan y cargan los mensajes
generados automticamente por GeneXus as como las reglas Msg y Error definidos en la transaccin.
Se recomienda que siempre se recupere la lista de estos mensajes y se haga un manejo de errores.
Los mensajes ms comunes generados automticamente por GeneXus son:
Las reglas Msg y Error aceptan en su definicin adems del parmetro con el mensaje a desplegar, un
segundo parmetro que define el Identificador del mensaje. El objetivo es que cuando se ejecute la
transaccin como Bussiness Component, y se obtenga la lista de mensajes ocurridos luego de ejecutar
una accin sobre la base de datos, se tenga de cada mensaje, adems del mensaje en s, su
identificador, siendo posible as evaluar el identificador del mensaje para codificar el comportamiento en
consecuencia:
Msg|Error(<mensaje>, <Id del mensaje>)
Ejemplos de <Id del mensaje>: "1", "2", "Error1", "Error2" o una descripcin como ser
"CustomerNameCannotBeEmpty", etc.
De no especificar un identificador para el mensaje, habr que preguntar por el texto del mensaje.
Nota: Para los mensajes generados automticamente por GeneXus, el Id es siempre en Ingls
(independientemente del idioma seleccionado en el modelo).
277
Business Components
Caso de uso
278
Business Components
Otra opcin
Adelantndonos aqu a presentar el otro tipo de objeto interactivo que estudiaremos un poco ms
adelante, el Web Panel, mostramos un objeto de este tipo en ejecucin. Su funcin ser pedir al usuario
final un par de valores, que almacenar en las variables correspondientes de tipo Date (&start y &end) y
luego, cuando el usuario presione el botn asociado al Evento Enter del Web Panel, se ejecutar su
cdigo.
Obsrvese que el cdigo es idntico al del procedimiento visto antes. Con este ejemplo pretendemos
mostrar que mediante un Business Component puede actualizarse la base de datos desde cualquier
objeto GeneXus.
279
Business Components
Caso de uso interactivo
Problema:seinsertapassolosisetieneclientenuevodel
mismoynopuedequedarpassinclienteenelsistema.
1
3
si se
cae el
sistema
aqu?
2 commit automtico
commit automtico
Recordemos que no se puede armar una sla UTL con dos transacciones.
Entonces?
Supongamos que cada vez que se inserta un nuevo pas en el sistema, es necesariamente debido a
que se tiene un nuevo cliente de ese pas. Supongamos que como requerimiento, adems, no debe
quedar bajo ninguna circunstancia ingresado un pas sin por lo menos un cliente asociado.
Tal como tenemos implementada la aplicacin, esto no se est controlando. Cmo se ingresa un pas
y un cliente para el mismo? El usuario debe ejecutar la transaccin Country, ingresar el pas. Luego
abrir la transaccin Customer, e ingresar los datos del cliente y confirmar. Pero qu suceder si se cae
el sistema cuando se est ingresando el cliente? Quedar el pas ingresado (recordar que cada
transaccin por defecto hace commit al final).
280
Business Components
Caso de uso interactivo
Solucin:enlatransaccinCountry,crearvariable&customer de
tipoBCCustomer einsertarlaenelForm yagregarreglaAccept.
1
&customer.CountryId = CountryId
on AfterInsert;
&customer.Save() on AfterInsert;
msg( It fails) if &customer.Fail()
on AfterInsert;
Commit automtico
Desventaja: no se dispararn en
forma interactiva las reglas
asociadas a Customer...
Necesitamos que la insercin del pas en la tabla COUNTRY y la insercin del cliente en la tabla
CUSTOMER se realicen dentro de una misma UTL. Como hemos visto, las operaciones efectuadas por
dos transacciones no pueden incluirse en una nica UTL. Por esta razn, necesitaremos hacer la
insercin dentro de la misma transaccin.
Cmo? Dentro de la transaccin Country, definimos una variable &customer, de tipo business
component Customer (para ello, tendremos previamente que haber prendido la propiedad Business
Component de la transaccin Customer, de manera tal que se cree este tipo de datos en la KB). Una
vez efectuado esto, simplemente insertando en el form la variable (al igual que suceda con un SDT),
GeneXus colocar controles para cada uno de los miembros de la estructura: &customer.CustomerId,
&customer.CustomerName, &customer.CustomerAddress, etc.
Las variables por defecto en las transacciones son de salida, por lo que habr que especificar regla
Accept para que puedan ser de escritura en ejecucin y el usuario pueda ingresar valores para las
mismas.
El Save del customer deber realizarse necesariamente luego de insertarse el pas en su tabla (de lo
contrario fallar la integridad referencial). Por tanto en las reglas:
&customer.Save() on AfterInsert;
Sabemos que en este momento ya se habr grabado el registro correspondiente al pas, y luego vendr
este Save... a continuacin, el commit automtico.
281
Business Components
Resumen
Objetivo:
Reutilizarlalgicadelnegociodefinidaenlastransacciones.Usarel
poderdelastransacciones(sinsusforms)desdeotrosobjetosGeneXus:
Procedimientos,WebPanels...
desdeotraTransaccin(aligualqueunavariablepodallenarse
interactivamenteinsertndolaenelForm,tambinunBC)
Beneficios:
ActualizacinalaBDgarantizandointegridaddelosdatosyejecucinde
lasreglasdelnegocio.
Reutilizacindecdigo(nonecesidaddeduplicarreglasdenegocio)
VariosobjetosGeneXus puedenactualizarlaBD.
282
Business Components
Reglas y Eventos
Reglas:sonejecutadastodaslasreglasdelatransaccinexcepto
(sonignoradasporelespecificador):
lasqueincluyenuser interface (Ej:Customer.call(),
lasquenoaplican:parm,prompt,NoPrompt,Default_mode,etc
Eventos:todosloseventosdelatransaccinsonignorados,
exceptoloseventosStart yAfter TRN(ysistosincluyen
referenciasaobjetosconuser interface,seignoran).
Nota: cuando decimos se ignora nos referimos en el contexto de la
actualizacin utilizando BC, no cuando la actualizacin se realiza a travs
de la propia transaccin.
Si existe una regla que invoca a un objeto que tiene interfaz, es decir, form, esa regla no se incluye en el
BC. Existe una forma de especificar que una regla declarada en la transaccin no aplique cuando se
ejecuta la transaccin, sino solo cuando se ejecuta el Business Component asociado: es calificando la
regla con [BC].
Ejemplo:
[BC] Default( BillDate, &today);
Si se quiere calificar de una sola vez un conjunto de reglas:
[BC]
{
regla1;
regla2;
...
reglan;
}
Lo mismo vale para eventos.
Anlogamente, existen calificadores para indicar que una regla solo se ejecute si se est corriendo la
transaccin con su form web: [WEB].
283
Actualizacin no
interactiva directa
Procedimientos
284
Procedimientos
Update
Nohayuncomandoespecficoparamodificarunregistro:se
realizaenformaimplcitadentrodelcomandoFor each.
Ejemplo:
parm( in: CustomerId, in: &StartDate, in: &EndDate);
285
Procedimientos
Update
LaactualizacinserealizaenelEndfor.
No secontrolaintegridadreferencial.
SiseactualizaunatributoqueesFK nosecontrolaexistencia.
Sloserealizacontroldeduplicados:
Si dentro de for each se intenta actualizar un atributo
para el que hay definido ndice unique, y existe
duplicado el valor, no se actualiza... de existir
clusula when duplicate se ejecuta su cdigo.
B*
E
F
286
Procedimientos
Update
Eficiencia:
for each
where InvoiceDate >= &StartDate
where InvoiceDate <= &EndDate
InvoicePendingFlag = False
endfor
Actualizacinmasiva:clusulaBlocking reducenmerode
accesosalaBD.
for each
where InvoiceDate >= &StartDate
where InvoiceDate <= &EndDate
Blocking 1000
InvoicePendingFlag = False
endfor
287
Procedimientos
Delete
Paraeliminarregistrosdeunatabla:ComandoDelete.
DebeirdentrodeunFor each.
Eliminaelregistrodelatablabaseenelqueseest posicionado.
Seejecutanibienseencuentraelcomando(ynoenelEndfor).
Nocontrolaintegridadreferencial.
Ejemplo:
For each
defined by InvoiceDate
Blocking 1000
Delete
Endfor
Para eliminar datos se utiliza el comando Delete dentro del comando For each.
El comando Delete elimina el registro en el que se est posicionado en un momento dado. Es
por ello que no puede aparecer suelto dentro del Source. Debe colocarse dentro de un
comando For each, cuya tabla base sea la tabla de la que se quieren eliminar registros. Solo se
eliminan los registros de la tabla base, no de la extendida.
Si deseamos eliminar todas las facturas anteriores a una fecha dada, podemos programar un
procedimiento:
For each
where InvoiceDate <=&date
For each
defined by InvoiceDetailQuantity
DELETE
Endfor
DELETE //luego de eliminar las lneas se elimina el cabezal
Endfor
Para mayor eficiencia en la eliminacin, dependiendo del nmero de registros de la base de
datos, convendr agregar clusula Blocking con un factor de bloqueo, N, adecuado. Por
ejemplo, si se agrega Blocking 1000 la eliminacin fsica no se realizar en cada iteracin,
sino que cada 1000 veces que se llegue al Endfor, se eliminarn el grupo de 1000 registros en
un nico acceso a la Base de Datos (en lugar de 1000).
288
Procedimientos
Insert
ComandoNew:permiteinsertarunregistroenunatabla.
Procedimiento NewPrice
New
ProductId = &ProductId
ProductPriceListDate = &today
ProductPriceListPrice = &price
endnew
Nocontrolaintegridadreferencial.
Realizaelcontroldeduplicados:
Si ya existe registro para el producto
y fecha? actualizar el precio:
clusula when duplicate.
New
ProductId = &ProductId
ProductPriceListDate = &today
ProductPriceListPrice = &price
when duplicate
for each
ProductPriceListPrice = &price
endfor
endnew
289
Procedimientos
Insert
Ejemplo:siquisiramosrealizarlageneracinderecibos
directamenteenunprocedimiento(noatravsdeBC).
For each using ActiveCustomers()
New
Blocking 1000
BillDate = &Today
BillInvoicePeriodStartDate = &start
BillInvoicePeriodEndDate = &end
BillAmount = sum( InvoiceAmount, InvoiceDate >= &start and
InvoiceDate <= &end and
InvoicePendingFlag )
Endnew
endfor
En el for each se
recorren los
clientes activos
y el new inserta
en la tabla BILL
un nuevo recibo
para ese cliente
(por qu
CustomerId no
aparece
asignado?).
El caso ms comn ser tener el comando new dentro de un for each, dado que en general se
quieren insertar registros en base a clculos efectuados en funcin de otros.
El mismo proceso de generacin de recibos que habamos resuelto anteriormente utilizando
Data Provider y Business Component, podramos realizarlo con un procedimiento que utilice el
comando new de insercin. Cul alternativa elegira usted? Recuerde que con los comandos
de actualizacin dentro de procedimientos, el nico control que se realiza es el de duplicados.
Si las inserciones son muchas, as como vimos para el caso de las actualizaciones,
disponemos de la clusula blocking para ir guardando en un buffer y luego hacer la insercin
de todos esos registros a la vez.
En nuestro caso no fallar la insercin, debido a que la clave primaria es autonumber, y que no
tenemos claves candidatas (va ndices unique) en la tabla de recibos (BILL).
Pero si no fuera el caso, como las inserciones se van realizando en el buffer hasta llegar a la
1000, no es posible hasta completar el buffer saber si alguna operacin fallar. Cuando se
ejecuta el INSERT masivo de base de datos, all s puede fallar alguna insercin. En ese caso,
se itera en los elementos del buffer, ejecutando el INSERT simple, uno por uno. Si existe
clusula When duplicate en el New, entonces por los registros que fallen, se ejecutar la
clusula.
290
Procedimientos
Insert
Sintaxis delnew
new
[ Defined by att1,, attN ]
[ Blocking NumericExpression ]
bloque_asignaciones1
[ when duplicate
For each
bloque_asignaciones2
Endfor ]
endnew
att1,, attN
attx1 = ...
...
attxm = ...
deben
pertenecer a
una tabla fsica
tabla base
Nota: No es necesario asignar valor a todos y cada uno de los atributos de la tabla.
Algunos vienen instanciados por el contexto del new (ej: si est dentro de un for each)
y no es necesario asignarles valor para el registro a insertar (toman el del contexto).
Actualizacin BD
BC versus Proc
Actualizacin va BusinessComponent:
Serealizan controles deintegridad referencial.
Secontrolan duplicados.
Sedisparan las reglas delnegocio.
292
Uso de Subtipos
293
Definicin de subtipos
LasrelacionesentreatributosGeneXusseestablecenatravsde
susnombres.
Mediantesubtipossepuedeestablecerquedosatributosquese
llamandiferente correspondenalmismoconcepto.
Casosdesubtipos:
A.Mltiplesreferencias
B.Especializacindeunnivel(relacin11)
C.Subtiposrecursivos
294
A. Mltiples referencias
Atributosconceptualmenteigualesquecumplenrolesdiferentes
(ej.:reservasdepasajes).
Reservation
City
PROBLEMA
Atributos con
el mismo
nombre
ReservationId*
CityId
origen
CityId
destino
{
CityId *
CityName
SOLUCION
}
Reservation
{
ReservationId*
ReservationCityFromId
ReservationCityToId
Desaparece
el problema!
City
subtipo
subtipo
{
CityId *
CityName
}
Realidad a representar/disear:
En cada reserva hay dos ciudades involucradas, las cuales cumplen roles diferentes.
El rol de una de las ciudades es el de ser la ciudad de partida (ciudad origen) y el rol de la
otra es el de ciudad de arribo (ciudad destino).
El dominio de ambas ciudades es el mismo, el de la tabla CITY.
La forma de representar que tanto el origen como el destino son ciudades de la tabla CITY,
es diseando la transaccin Reservation en la forma mencionada inicialmente en la
transparencia. Sin embargo, no es posible que en la estructura de una transaccin figure el
mismo atributo ms de una vez, pues no habra manera de identificarlos.
SOLUCIN: llamar a las dos ciudades de la reserva con diferentes nombres de atributos.
Cualquiera de las siguientes opciones es vlida. Elegimos la 3era por mayor claridad.
Opcin 1) ReservationCityFromId ciudad origen
CityId ciudad destino (mismo nombre que la PK de CITY)
Opcin 2) CityId ciudad origen (mismo nombre que la PK de CITY)
ReservationCityToId ciudad destino
Opcin 3) ReservationCityFromId ciudad origen
ReservationCityToId ciudad destino
El problema es que al poner por ejemplo ReservationCityFromId en lugar de CityId, GeneXus
deja de inferir que ReservationCityFromId corresponde al cdigo de una ciudad de la tabla de
CITY. Cmo hacemos para relacionarlos, siendo que tienen diferente nombre de atributo? ver
respuesta en prxima hoja
295
Para estos casos GeneXus provee los SUBTIPOS, que permiten definir que dos atributos que
se llaman diferente corresponden al mismo concepto.
En nuestro ejemplo, si definimos al atributo ReservationCityFromId como subtipo de CityId,
estamos especificando que si bien ReservationCityFromId y CityId son diferentes atributos (de
nombres diferentes), corresponden, no obstante, al mismo concepto (una ciudad de la tabla
CITY).
Al establecer que un atributo es subtipo de otro, estamos estableciendo una dependencia
funcional entre ellos.
Si ReservationCityFromId es subtipo de CityId, entonces decimos que CityId es el supertipo
de ReservationCityFromId.
Los atributos que se encuentran en una relacin subtipo-supertipo comparten la misma
definicin (tipo de datos).
Se realizan los controles de integridad referencial automticamente.
La tabla extendida que se obtiene con la definicin del subtipo, es la misma que se obtendra
si se utilizara directamente el supertipo.
296
A. Mltiples referencias
Conladefinicindelossubtiposantesmencionados:
Seestablecenlassiguientesrelaciones:
ReservationCityFromId
RESERVATION
ReservationCityToId
CITY
LosatributossecundariosdeCITY:
Pertenecen a la tabla extendida de RESERVATION, pero al existir doble
referencia no se pueden utilizar directamente desde RESERVATION
(ambigedaddecaminosyconvaloresdeciudades diferentes).
Solucin definirtambinsubtiposparalosatributossecundariosde
CITY,eincluirlosenc/udelosgruposdesubtipos.
IMPORTANTE:
Notar que este caso de mltiples referencias puede darse tanto:
en la tabla base (*)
como en la tabla extendida
(*) es el caso del ejemplo, en el que en la propia tabla (RESERVATION) hay ms de una
referencia a otra tabla (CITY) y con valores diferentes.
RESUMIENDO:
siempre que desde una tabla se accede a otra que est en su tabla extendida por ms de un
camino y con valores diferentes, es necesario definir SUBTIPOS, para poder llamarle
diferente a los atributos y hacindose automticamente todos los controles de integridad
referencial.
Una vez definidos los grupos de subtipos que sean necesarios, la forma de indicarle a
GeneXus cul de los caminos debe tomar para acceder a la tabla destino, es mencionando los
nombres de atributos que correspondan. Ej.: mencionar ReservationCityFromName si lo que
se necesita en ese momento es el nombre de la ciudad origen, o mencionar
ReservationCityToName si lo que se necesita es el nombre de la ciudad destino.
297
A. Mltiples referencias
Nombre de
cada grupo
de subtipos.
Transaccin Reservation
Tabla Reservation
{
ReservationId*
ReservationCityFromId
ReservationCityFromName
ReservationCityToId
ReservationCityToName
ReservationId*
ReservationCityFromId
ReservationCityToId
Inferido
Inferido
FK
FK
Con el grupo estamos indicando que los atributos pertenecientes al mismo grupo de subtipos,
estn relacionados. Por ej., en nuestro ejemplo, GeneXus sabr que el atributo
ReservationCityToName ser inferido a travs del atributo ReservationCityToId (y no a travs
del ReservationCityFromId). Esto es por pertenecer ambos al mismo grupo (al de nombre
ReservationCityTo).
Cuando el usuario digite un valor sobre ReservationCityToId, no solo se va a hacer
automticamente el control de integridad referencial (que exista un ciudad con ese cdigo en la
tabla CITY), sino que se va a inferir en ReservationCityToName el nombre correspondiente a
ese cdigo de ciudad.
IMPORTANTE: Todo grupo de subtipos, debe contener un atributo o conjunto de atributos,
cuyos supertipos, juntos, correspondan a la clave primaria de una tabla del modelo.
Los dems atributos del grupo debern ser de tipo Inferred, es decir, debern poder inferirse
a travs de esa clave.
En caso contrario estar mal definido el grupo.
298
CUSTOMER
COUNTRY
SALE
SELLER
Source:
Otro camino desde SALE a COUNTRY: a travs del Pas del vendedor (CountryId)
qu pas imprime?
cul de los caminos toma?
Hay una ambigedad en el modelo de datos!
Layout:
Si quisiramos por ejemplo listar las ventas (SALE), y de c/u de ellas mostrar los datos del
cliente (nombre, pas, etc.) y del vendedor (nombre, pas, etc.):
necesitamos un for each con tabla base SALE y acceder a travs de su extendida a
las tablas CUSTOMER, SELLER y COUNTRY para listar los atributos secundarios del
cliente, vendedor y pas respectivamente.
Problema:
Los atributos de nombre CountryId, CountryName y todos los de la tabla
extendida de COUNTRY pertenecen a la tabla extendida de SALE por dos
caminos diferentes: 1) a travs del pas del cliente y 2) a travs del pas del
vendedor.
Solucin:
Debemos diferenciarlos, llamarlos con diferente nombre de atributo pero
queriendo que se sigan representando todas las relaciones y hacindose
automticamente todos los controles de integridad referencial.
299
Solucin
SALE
eC
Sal
o
ust
rId
me
CUSTOMER
COUNTRY
Sal
eSe
ller
Id
SELLER
Cuando queremos el pas del vendedor de la venta: SaleSellerCustomerName
Una vez definidos los dos grupos de subtipos que se muestran en la figura, y haciendo el
cambio correspondiente en la estructura de la transaccin Sale, queda resuelta la ambigedad
en el modelo de datos!
300
SaleSellerCountryId
Problema resuelto!
Una vez definidos los subtipos, tenemos que recordar usar el nombre de atributo que
corresponda a lo que queremos acceder. Por ejemplo, en todos aquellos objetos GeneXus en
los cuales queramos acceder al cdigo o al nombre del pas del cliente de la venta debemos
usar los atributos SaleCustomerCountryId y SaleCustomerCountryName respectivamente.
301
B. Especializacin de atributos
Ej.: Sistema para una Universidad
PERSON
TEACHER
STUDENT
datos propios de
los profesores
datos propios de
los estudiantes
Sistema
Teachers
Sistema
Students
B. Especializacin de atributos
Person
{
Teacher
{
PersonId*
PersonName
PersonAddress
Student
{
TeacherId*
TeacherName
TeacherAddress
TeacherSalary
}
}
StudentId*
StudentName
StudentAddress
StudentAverage
}
La transaccin Teacher tiene asociada una tabla que contendr fsicamente slo dos
atributos: TeacherId y TeacherSalary.
Al ser TeacherId identificador de la transaccin, ser la clave primaria de la tabla asociada.
Adems, al ser un subtipo de PersonId, ser una clave fornea a la tabla PERSON. Por lo
tanto, se harn los chequeos de integridad referencial correspondientes.
Los atributos TeacherName y TeacherAddress son subtipos de PersonName y de
PersonAddress respectivamente y estn agrupados con TeacherId, por lo que sern inferidos
de la tabla PERSON, a travs de la clave fornea TeacherId (no estn almacenados en la tabla
TEACHER).
303
C. Subtipos recursivos
Ejemplo:EmployeeManager
Tabla
EMPLOYEE
{
EmployeeId*
EmployeeName
EmployeeIsManagerFlag
EmployeeManagerId
Error(Debe ingresar un gerente para el empleado)
if not EmployeeIsManagerFlag and
EmployeeManagerId.isnull();
FK
304
C. Subtipos recursivos
Listadodenavegacindetallado:
305
Consideraciones
Cuandosedefineunsubtiposte"hereda"ladefinicindel
supertipo.
Al menos uno de los supertipos del grupo (o conjunto de
supertipos del grupo) debe(n) corresponder a la PK de una
tabladelmodelo.
306
Patterns
307
Patterns: Escenario
Paginacin
308
Patterns: Escenario
New Country
Update Country
Delete Country
T
r
a
n
s
a
c
t
i
o
n
...as como poder ingresar un nuevo pas (mediante la transaccin Country), o seleccionar uno de los
mostrados en el grid, para poder modificarlo o eliminarlo...
309
Patterns: Escenario
...o incluso ver la informacin completa de ese pas, incluyendo los clientes asociados...
310
Patterns
Generalidades
Definicin
Patrones que se pueden aplicar a una KB para
implementar automticamente cierta funcionalidad.
Patrones disponibles:
Work With
Category
Selectores dentro de
las Transacciones
Una vez aplicado el patrn, todos los objetos generados quedan como
parte de la Base de Conocimiento.
Es natural al desarrollar aplicaciones, tener que resolver partes muy similares pero no exactamente
iguales.
Por ejemplo, si en una Base de Conocimiento se tienen modelados los objetos de la realidad Customers
y Countries, a pesar de ser dichos objetos bien diferentes, los Work With Customers y Work With
Countries respectivamente, tienen muchas cosas en comn: un grid en el form, un conjunto de
variables para utilizar en filtros, opciones de ordenamiento de la consulta, invocaciones a la transaccin
correspondiente para actualizar la base de datos, etc..
Surgen entonces los Patterns, que ofrecen la posibilidad de aplicar un patrn (pattern) a las instancias
que se deseen de una Base de Conocimiento, y generar todos los objetos GeneXus necesarios para
implementar cierta funcionalidad, teniendo en cuenta sus datos especficos.
Siguiendo con el ejemplo mencionado inicialmente, es posible aplicar el patrn Work With a la Base de
Conocimiento, de forma tal que partiendo de las transacciones Customer y Country, se obtenga todo
el desarrollo correspondiente al Work With Customers y Work With Countries para ambiente web
(pantallas vistosas que implementan las consultas, con ordenamientos, filtros, invocaciones a las
transacciones correspondientes, y ms).
311
Patterns
Work With
Genera a partir de una Transaccin:
Pantalla Work With: consulta interactiva, mltiples ordenamientos,
filtros, invocacin a la transaccin, etc.
Pantalla View: Registro seleccionado, con la informacin asociada.
WorkWith
Transaccin
View
312
Patterns
Aplicacin
Abrir la Transaccin.
Seleccionar el patrn a aplicar
(aparecer la instancia por
defecto).
Marcar la opcin Apply this
pattern on save.
Grabar la Transaccin.
Para aplicar el pattern sin demoras, alcanzar con editar la instancia (selector Work With de la
transaccin), marcar el check box y grabar. Listo! Con eso se crearn automticamente los objetos
GeneXus que implementan el pattern (en particular la pantalla de seleccin y filtro y la pantalla de View
que mostramos antes). Asimismo se modificar la transaccin para que ahora reciba por parmetro el
modo (Insert, Update, Delete, Display) y el pas.
313
Patterns
Work With: objetos generados
Consecuencia: Se generan en la KB los objetos que ya vimos en ejecucin.
Dnde? En el Folder View, bajo la propia transaccin:
Una vez grabada la instancia, en el folder view, bajo el nombre de la transaccin, aparecer el nombre
del pattern aplicado a la misma (en nuestro ejemplo WorkWithCountry) y todos los objetos que GeneXus
debe crear para implementarlo.
En nuestro caso se crearn 2 objetos de tipo Web Component, y 2 objetos de tipo Web Panel. Son muy
similiares. La diferencia es que un Web Component puede incluirse dentro de otro objeto. No
entraremos en detalles en este momento.
314
Patterns
Ejemplo
Aplicacin del pattern Work With a la transaccin Country.
315
Patterns
Comenzando a asociar... pantalla Work With
Se sita en el pas
indicado, o muestra
todos los pases.
Son muchas las propiedades que se ofrecen en las instancias correspondientes al patrn Work With,
para personalizar el comportamiento de los objetos que se generarn. A continuacin describimos
algunas de ellas.
El nodo Selection ofrece las propiedades relacionadas a la pantalla Work With que se generar para la
instancia. Sus sub-nodos son:
Modes (Ins, Upd, Del, Dis)
Este nodo permite definir en cules modos se ofrecer invocar a la transaccin. Las posibilidades y sus
valores por defecto son:
Insert: True
Update: True
Delete: True
Display: False
En la instancia aparece <default> al lado de cada una de las propiedades anteriores. Dnde se
configura este valor por defecto? Lo veremos unas pginas ms adelante.
Para cada modo podr especificarse una condicin. Se proveen las siguientes propiedades para ese
propsito: Insert Condition, Update Condition, Delete Condition, Display Condition.
Si se define una condicin asociada a un modo, la invocacin para ese modo solo se habilitar si la
evaluacin de la condicin es verdadera (Ejemplo: CountryId=10).
316
Patterns
Personalizacin... pantalla Work With
Attributes
Este nodo permite definir cules atributos se desean mostrar en el grid (y para cada atributo, se pueden
personalizar sus propiedades). Por defecto muestra todos los atributos de la estructura de la
transaccin.
Orders
Es posible ofrecer al usuario final varios rdenes posibles para ver el resultado de la consulta (es decir,
las lneas mostrando los datos en el grid). Utilizando el botn derecho del mouse se puede definir un
nuevo orden (su nombre y composicin). Cada orden puede estar compuesto por varios atributos
(pudiendo indicar para cada uno de ellos si se desea orden ascendente o descendente). Se presentar
un combobox en la pantalla Work With ofreciendo todos los rdenes posibles de seleccionar, para que
el usuario final elija uno y los datos se presenten en el grid ordenados por el mismo. Sin embargo, el
control grid ya presenta la posibilidad de ordenar en ejecucin, simplemente cliqueando sobre la
columna por la que se desean tener ordenados los datos. Pero hay que tener en cuenta que esa
funcionalidad solo permite ordenar en ejecucin los datos de la pgina del grid que se est mostrando.
Filter
Este nodo permite definir condiciones de filtro, para que en el grid se muestren solo los registros que
cumplan con las mismas.
Actions
El nodo Actions permite incorporar acciones propias a la pantalla Work With. Es decir, permite agregar
botones (dentro o fuera del grid) que invoquen a los objetos que se indiquen, con sus correspondientes
parmetros. Si bien el nodo Actions no est visible por defecto, estando posicionado en el nodo
Selection y presionando el botn derecho del mouse, se ofrecer la opcin Add Actions que lo
agregar. Una vez agregado este nodo, estando posicionado sobre el mismo y presionando el botn
derecho del mouse, se ofrecer la opcin Add Action que permitir agregar una accin con su nombre
de accin, caption, objeto invocado, etc.
317
Patterns
Personalizacin - Ejemplos
1) Ocultar atributo CountryId del grid.
F4
El atributo CountryId, a diferencia del CountryName, no puede ser eliminado del grid, debido a que es el
atributo que se enva a la transaccin Country cuando el usuario desea modificar o eliminar el pas
mostrado en una lnea del grid del Work With.
318
Patterns
Personalizacin - Ejemplos
2) Eliminar modo Delete desde el grid.
F4
Al editar las propiedades estando posicionados en el nodo de la instancia que se muestra, podemos
observar que cada uno de los modos en que se puede invocar una transaccin (para insertar, modificar,
eliminar o incluso deplegar) estn listados como propiedades.
Podemos ver tambin que aparece una propiedad Export que permite exportar los datos a una planilla
excel.
Otra vez aqu podemos apreciar que cada una de las propiedades tiene el valor <default> que an no
sabemos de dnde es tomado. Pero si queremos fijar un valor independiente de cul sea el default,
podemos editar el combo box que presentar tres valores: <default>, true, o false.
Hemos fijado el valor de la propiedad Delete en false. Podemos ver en ejecucin la repercusin. Ya no
aparece en el grid la primera columna que contena la imagen que permita eliminar el pas. Ahora no se
podr desde esta pantalla eliminar pases.
Obsrvese tambin cmo ha desaparecido del grid el atributo CountryId. Lo habamos ocultado en la
pgina anterior.
319
Patterns
Personalizacin - Ejemplos
3) Agregar una Accin a la pantalla Work With Countries que
invoque al proceso de facturacin: BillingProcess.
a) Clic con el botn derecho
sobre el nodo Selection
320
Patterns
Personalizacin - Ejemplos
c) Definir la Accin editando sus
propiedades (F4).
Nombre de la accin y
objeto que se invoca.
d) Finalmente en ejecucin, se
observa el botn fuera del grid.
Ya habamos definido el objeto BillingProcess para realizar la facturacin del mes a todos los clientes.
Aqu estamos agregando un botn fuera del grid, que al presionarlo llama a este otro objeto GeneXus
que habamos creado antes.
321
Patterns
Asociando... pantalla View
El nodo View por su parte, ofrece las propiedades relacionadas a la pantalla View que se generar para
la instancia. Muestra toda la informacin de un registro, que fue seleccionado en el grid del Work With
(la informacin del registro es mostrada en una solapa de un tab control, y adems hay una solapa con
un grid por cada tabla directamente subordinada, para mostrar la informacin relacionada).
322
Patterns
Personalizacin - Ejemplos
1) Quitar atributos CustomerGender y CustomerStatus del tab
Customer de la pantalla View Country.
En este caso si no queremos que los atributos CustomerGender y CustomerStatus se vean en el grid en
ejecucin, no necesitamos ocultarlos. Podemos directamente eliminarlos.
323
Patterns
Personalizacin - Ejemplos
2) Agregar un filtro por CustomerName en el tab Customer.
Una vez que ejecuta el paso a) y elige Filter aparecer un nuevo nodo Filter inmediatamente despus
del nodo Attributes, con 2 subnodos: Attributes y Conditions.
Luego, en el paso b), deber posicionarse en el subnodo Attributes y hacer botn derecho, donde se le
ofrecer la posibilidad de agregar un atributo de filtro. Al editar las propiedades, usted deber presionar
el combo box que le desplegar una ventana donde ingresar el atributo (en nuestro caso,
CustomerName). Con esto se crear automticamente una variable de igual nombre que el atributo
&CustomerName, que ser el control que aparecer en ejecucin para que el usuario digite all el filtro.
Veamos el paso siguiente...
324
Patterns
Personalizacin - Ejemplos
(Continuacin)
c) Definir la condicin correspondiente.
325
Patterns
Valores por defecto para las propiedades
Propiedades (F4)
El patrn Work With adems de generar objetos nuevos, tambin modifica las transacciones, para que
sean invocadas por los objetos generados por el pattern, agregndoles regla parm, etc.
Relacionado a esto, cada instancia contiene la propiedad UpdateTransaction, que ofrece los siguientes
valores:
Do not update: La transaccin no ser modificada (web form, reglas y eventos sern mantenidos).
Only rules and events: Solo las reglas y eventos se modificarn, no se modifica el web form.
Apply WW Style: La primera vez que se aplique el patrn, el comportamiento ser el mismo que si se
hubiese seleccionado el valor Create Default. A partir de la segunda vez que se aplique el patrn, no se
modificar la data area del form de la transaccin (por si se personaliz y se desea mantener), y s se
modificar el style area, as como los eventos y reglas.
Create default: Reglas, eventos y form de la transaccin (tanto data area como style area) sern
modificados. En lo que respecta al form, ser como seleccionar la opcin Apply default (Web Form).
El valor por defecto para esta propiedad es Only rules and events.
En cuanto a las propiedades AfterInsert, AfterUpdate y AfterDelete, permiten definir el
comportamiento luego de que se inserta, modifica o elimina un registro.
Los valores posibles para cada una de ellas son:
<default>
Return to caller
Go to View
Go to Selection
Otra vez el valor <default>. Lleg el momento de ver dnde se configuran todos estos valores por
defecto que hemos ido encontrando en la instancia...
326
Patterns
Pattern Settings
Configuracin de propiedades generales (para todas las instancias).
En este lugar estn centralizados los <default> para toda instancia. Podemos ver que en el nodo
Template se ofrecen algunas de las propiedades que mencionamos en la pgina anterior.
El tamao de pgina de los grids del work with, que en las imgenes anteriores era de 3 (se mostraban
3 lneas por pgina del grid) se configura en el nodo Grid. El valor por defecto de esta propiedad es
Page.Rows. Es decir, el valor del dominio enumerado Pages creado por GeneXus automticamente al
aplicar el pattern por primera vez. El valor que tiene Page es 10. Nosotros lo habamos cambiado a 3
para que nos entraran las imgenes completas en estas slides.
327
Patterns
Dinamismo entre la Transaccin y Patterns
TodoslosobjetosgeneradosporPatterns estnbasadosenelesquemade
Defaults deGeneXus.CadapartedeunobjetoesgeneradacomoDefault..
LaimplementacinbasadaenDefaults permitetenerdinamismoentrela
Transaccinyelpatrn.
No es necesario reaplicar el patrn, los cambios se ven al abrir
nuevamente el objeto
Eldinamismosemantieneparatodaslaspartesdefault delobjeto
OpcinEdit /Apply Default delMen paravolveraldefault deunaparteode
todaslaspartes(All parts)
Ejemplo:siagregamosatributoCountryFlag alaestructuradeCountry,qu
pasar conelgrid delWork With Countries?SisteconservaelDefaul,ser
agregadaautomticamentecolumnaCountryFlag algrid.
El dinamismo mencionado se mantiene para todas las partes default de los objetos.
Todos los objetos generados por Patterns estn basados en el esquema de Defaults de GeneXus.
Cada parte (Form, Reglas, Eventos) de cada objeto es generado como Default. Si se modifica alguna
parte del objeto, sta deja de ser Default.
Por ejemplo, si se modifica el web form de un WW (no queda como default), y se agrega un nuevo
atributo a la transaccin, no se va a actualizar automticamente el grid del WW con ese atributo (o sea,
no se agregar dicho atributo).
La implementacin basada en Defaults permite tener dinamismo entre la Transaccin y el patrn
Cambiar propiedades en la definicin del patrn (Pattern setting)
Cambios en la instancia (agregar un nuevo filtro)
Cambios en la Transaccin (agregar un nuevo atributo)
Si se quiere volver al dinamismo, se deber tener nuevamente las partes como default.
Para esto, se debe seleccionar desde el Men Edit / Apply Default (la parte donde se tiene abierto el
objeto) o Apply Default (All parts), lo cual vuelve a default todas las partes que se haban modificado.
328
Patterns
Cmo borrar los objetos generados por Patterns
Seleccionar la instancia en el Folder View, presionar botn derecho /
opcin Delete o presionar la tecla DEL. Aparecer el mensaje:
Al confirmar el mensaje:
329
330
Web Panels
Generalidades
Definicin Objetos GeneXus que permiten al usuario realizar
consultas interactivas a la base de datos a travs de una pantalla
en tiempo de ejecucin.
Son flexibles, por lo que se prestan para mltiples usos.
Algunos web panels conocidos:
Work With Countries.
View Country.
Elementos que los componen:
331
Web Panels
Event Enter
En el ejemplo, el web panel contiene dos variables &startDate y &endDate como se muestra arriba. En
tiempo de ejecucin, el usuario podr ingresar valores en las variables dado que en los web panels las
variables son por defecto de entrada (salvo las incluidas en grids, como veremos).
En el evento Enter del web panel (asociado al botn Billing Generation), se obtienen para cada cliente
las facturas cuyas fechas se encuentren en el rango especificado y se genera recibo para el cliente
(invocando al Data Provider que devuelve la coleccin de Business Components que ya hemos visto
oportunamente cuando estudiamos esos temas).
De modo que este web panel tiene como finalidad permitir al usuario ingresar un rango de fechas, y
presionando el botn Billing Generation, ejecutar el procesamiento de las facturas.
332
Web Panels
blob
CustomerPhoto
}
parm(in: CustomerId );
Se muestran los
datos del cliente
El web panel mostrado arriba ha sido creado para exhibir los datos de un cliente. Se necesita invocarlo desde otro
objeto (como ya veremos), pasndole por parmetro el cdigo del cliente del cual se quiere mostrar la informacin.
Un web panel es un objeto tpicamente utilizado para mostrar informacin. Entonces, cuando GeneXus encuentra
atributos en el form, qu intencin adjudicar al programador que los puso all? Pues, que le est pidiendo
implcitamente que vaya a buscar los datos correspondientes a la base de datos para desplegarlos.
En definitiva, con el web panel anterior, GeneXus ir a la tabla CUSTOMER y filtrando por el atributo recibido por
parmetro, CustomerId, mostrar la informacin del registro encontrado. Qu informacin? La que reside en los
atributos que figuran en el form. Pero el atributo CountryName no se encuentra en la tabla CUSTOMER. Pues
sucede lo mismo que con un for each, un grupo de Data Providers, etc., es decir, desde el registro de la tabla base,
se accede al registro relacionado de la tabla extendida que se necesite, para obtener el valor del atributo requerido
(en nuestro caso accede a la tabla COUNTRY para recuperar el valor de CountryName).
Las inferencias que GeneXus realiza son las siguientes:
Al tratarse de un web panel, los atributos que figuren sern de consulta1. Entonces GeneXus deber acceder a la
base de datos para recuperar sus valores. A qu tablas? Depender de si el Web panel tiene grids o no:
Web panel plano (sin grid): estn los atributos sueltos en el form, como en el caso que estamos mostrando. Si
esto sucede, es porque el analista necesita acceder a informacin de un registro de una tabla (y eventualmente de
los registros relacionados por tabla extendida), como es el caso del ejemplo. En este caso, el web panel estar bien
programado si adems se agrega un filtro que determine ese registro a mostrar. En nuestro caso, tenemos la regla
parm que al recibir en atributo PK de la tabla slo recuperar un registro. En definitiva, GeneXus determina una
tabla base del web panel, as como lo haca para un for each. Cmo? Buscando la mnima tabla extendida que
contenga a los atributos...
Web panel con uno o ms grids: lo veremos en lo que sigue, pero ya podemos intuirlo... qu sentido tendr
colocar un grid? Mostrar informacin repetitiva. En el caso general: cada grid mostrar muchos registros de una
tabla (y su informacin asociada).
-------------------------------------------------------------------------------------------------------------------1 Al contrario de lo que sucede con los atributos en las transacciones (salvo los inferidos o los que tienen regla
noaccept o propiedad Enabled deshabilitada).
333
Web Panels
CUSTOMER
COUNTRY
334
Web Panels
CountryId
CustomerName
Susan Jones
Richard Smith
Martina Rodrguez
Hugo Romero
...
...
...
Country table
CountryId
CountryName
Uruguay
United States
Italy
Venezuela
...
...
Base de datos
load
load
load
load
Cuando GeneXus puede determinar automticamente una tabla a recorrer para cargar las lneas del
grid, lo hace, y en ese caso no habr necesidad de brindarle esa informacin. Es por ello que decimos
que en ese caso hay un for each implcito. Luego veremos casos en los que esto no ocurre (grids sin
tabla base).
Obsrvese en el ejemplo, que si en la tabla base existen 4 registros, se cargarn uno a uno los cuatro.
Si ahora queremos que el usuario pueda filtrar los clientes que desea ver... ah entran en juego las
variables que hemos definido en la parte fija del form, como veremos en la pgina siguiente.
335
Web Panels
...filtrando
Por defecto
de entrada
Obsrvese cmo en la ventana de propiedades del control Grid, aparece una de nombre Conditions.
Cliqueando en el combo se abrir un editor para especificar las condiciones booleanas que debern
cumplir los registros para ser cargados como lneas del grid.
Es por esa razn que se han agregado las variables &CustomerName y &CountryName al form del web
panel, de manera tal que el usuario pueda ingresar all valores que operen como filtros sobre los datos a
mostrar. En nuestro caso, hemos establecido filtros con el operador like. Las variables en la parte plana
del form de web panels son por defecto de entrada. Luego veremos que en principio si estn en grids
sern por defecto de salida.
Obsrvese que las condiciones (separadas con ;) equivalen a las que aparecan en las clusulas
where de un for each (o grupo repetitivo de data provider).
De la misma manera, por cuestiones de optimizacin, puede determinarse, al igual que se haca en un
for each, criterio de ordenamiento de la tabla a recorrerse, como se muestra arriba en el ejemplo.
Nota: Asimismo, igual que en un procedimiento, no slo pueden establecerse condiciones locales al grid
(for each), sino tambin generales, mediante el selector Conditions. Esto tendr sentido cuando se
tenga ms de un grid (for each), para no tener que repetir la misma condicin cada vez.
336
Client
Web Panels
sh
Server
La propiedad Automatic Refresh que se encuentra a nivel del Web Panel puede tomar los siguientes valores:
When variables in conditions change (valor por defecto): luego de provocarse automticamente el refresh, se
dispara el evento Load cargndose el grid segn los nuevos valores de las variables.
No
Dependiendo del tipo de datos del filtro, y del control web utilizado para filtrar, la condicin ser aplicada cuando se
est digitando o al abandonar el campo.
En el caso de filtros en controles edit, para tipo de datos Character, son aplicados cuando el usuario los va
digitando. Para tipo de datos Date, DateTime y Numeric, las condiciones se evalan cuando se abandona el campo.
En el caso de filtros combo boxes o dynamic combos, las condiciones son evaluadas cuando se abandona el
campo. Para Check boxes y Radio buttons, las condiciones son evaluadas cuando el valor es cambiado.
Ejecucin: qu sucede en el cliente y en el servidor al tener la propiedad por defecto y un grid con tabla base?
1 ejecucin (variables vacas):
For each CUSTOMER
guardar en memoria CustomerName
acceder a registro de COUNTRY relacionado
guardar en memoria CountryName
cargar (load) lnea en el grid con ambos valores
337
Web Panels
Intencin: para aquellos clientes con estado On Hold poder activarlos marcando
check box y presionando botn Activate. Antes queremos:
1. Solo habilitar check box para los On Hold:
Cuando se carga cada lnea del grid, si el valor del atributo CustomerStatus de la tabla
CUSTOMER a ser cargado es On Hold, habilitar check box...
Ampliaremos la funcionalidad de nuestro web panel, permitiendo ver el estado de cada cliente, y para
aquellos que estn On Hold, brindando la posibilidad de pasarlos al estado Active.
Para hacer esto, agregaremos al grid el atributo CustomerStatus que muestra el estado, y una variable
booleana &Select, que permitir al usuario seleccionar aquellos clientes que desea activar. Adems un
botn para efectivamente activar todos los clientes marcados. Pero esto lo haremos en un segundo
paso.
Obsrvese que al ser el tipo de datos de la variable &select booleano, por defecto aparece en el grid
como un check box. Para asegurar que el usuario solamente intente activar clientes On Hold,
deseamos que solamente aparezca habilitado este check box cuando corresponde... para ello
necesitaremos programar la carga de cada lnea, esto es, el evento Load...
338
Web Panels
Customer table
CustomerId
CustomerStatus
...
CustomerName
Susan Jones
...
Richard Smith
...
Martina Rodrguez
...
Hugo Romero
...
...
...
...
En la seccin Events del web panel, programamos el evento Load del grid que vemos arriba. En el
ejemplo, customerGrid es el nombre que hemos dado al control grid en el form.
Al tratarse de un web panel con un nico grid, tambin podramos haber programado el evento Load a
secas:
Event Load
if CustomerStatus = Status.OnHold
&select.Enabled = 1
else
&select.Enabled = 0
endif
endevent
Es decir, en el caso de un web panel con un nico grid, no es necesario calificar el evento con el
nombre del grid. Igualmente recomendamos hacerlo, anticipndonos a la posibilidad futura de agregar
otro grid al form del web panel.
El evento Load se disparar por cada lnea que haya de cargarse en el grid, se encuentre ste
programado o no. Lo que hacemos en el ejemplo es aprovechar ese momento inmediatamente anterior
a la carga, para efectuar una accin. Y ese es el cdigo que incluimos en el evento.
Ahora s, estamos en condiciones de implementar la activacin, para lo que necesitaremos asociar al
botn un evento, que podr ser el evento Enter o uno de usuario...
339
Web Panels
&customer BC Customer
En el ejemplo, cuando el usuario presiona el botn Confirm, necesitamos recorrer todas las lneas del
grid, y para cada una de ellas, si el check box de la variable booleana &Select fue marcado por el
usuario, entonces debemos cambiar el estado del cliente correspondiente, de On Hold a Active.
Al insertar el botn en el form del web panel, y editar sus propiedades, podr observarse que por
defecto, el botn est asociado al 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 asocirselos a controles o de utilizar el evento Enter del
sistema.
Comando For each line, para recorrer las lneas 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 (tambin cuando se programan eventos OnClickEvent, Click,
etc., sobre alguna columna del grid).
Obsrvese que el comando For each line slo tiene en comn con el comando For each estudiado
antes, el hecho de representar una estructura repetitiva. La diferencia ms importante: mientras el for
each recorre registros de una tabla (base) de la base de datos, el for each line recorre las lneas de un
grid.
En nuestro ejemplo hemos definido una variable &customer, Business Component Customer, mediante
la cul cambiaremos a estado Active todas las lneas del grid marcadas por el usuario. Para ello
recorremos el grid con el comando for each line.
340
Web Panels
Otra posibilidad, en lugar de utilizar el evento del sistema Enter, es definir un evento de usuario. Ello se
consigue siguiendo los pasos que pueden verse arriba.
Como puede apreciarse, la mayora de los controles presentes en un form tienen la propiedad
OnClickEvent asociada. Esa propiedad permite especificar un evento a dispararse cuando el usuario
haga clic sobre el control. Podr ser un evento del sistema (Refresh, Enter) o uno definido por el
usuario.
341
Web Panels
No as las de la parte fija del web panel. Esas son por defecto de entrada, como ya hemos visto antes
para las variables que utilizamos para filtrar los customers mostrados en el grid.
Cmo desplegar datos en un grid
Por defecto todo atributo y variable que est dentro de un grid se despliega en ejecucin como texto, es
decir que es nicamente de lectura y por consiguiente no puede ser modificado.
Cmo aceptar datos en un grid
Es posible aceptar datos en las variables de un grid dependiendo de la programacin de los eventos
existentes en el objeto:
1. Si dentro de un evento del web panel se est utilizando el comando For each line, todas las
variables que estn dentro del grid pasan a ser de entrada. Es posible indicar en este caso cules
son las variables que no van a poder ser modificadas a travs de la propiedad ReadOnly.
2. Si dentro de la fila hay algn control con un evento click, dblClick, etc.. asociado ( evento de usuario
especificado en la propiedad OnClickEvent), suceder lo mismo.
342
Web Panels
Seguimos ampliando nuestro ejemplo; ahora queremos que el usuario pueda seleccionar una lnea del
grid (un cliente) y presionando botn Select customer poder invocar al web panel que habamos
implementado antes.
En este ejemplo vemos dos funcionalidades en juego:
La necesidad de colocar una columna en el grid oculta (no visible).
Permitir que el usuario seleccione una lnea del grid para hacer algo con ella.
Por qu colocar la columna correspondiente a CustomerId y ocultarla, en lugar de no agregarla en
absoluto? Reflexione sobre lo siguiente: el atributo CustomerId enviado por parmetro al ejecutarse el
evento Select customer, de dnde es extrado? De la base de datos? No, es el que est cargado en
el grid. Ms especficamente, por cada grid existir un archivo temporal que contendr tantas columnas
como las del grid, visibles y ocultas. Cuando el usuario selecciona en el grid la segunda lnea, y
presiona el botn Select customer, se est posicionado en ese archivo temporal, correspondiente a esa
lnea (y nunca en la base de datos!). Es por esta razn que de no colocar la columna correspondiente a
CustomerId en el grid, no estaramos pasando valor alguno a CustomerView.
Para permitir al usuario seleccionar una lnea del grid, alcanza con prender la propiedad
AllowSelection del grid.
343
Web Panels
propiedad Order
propiedad Conditions
propiedad Data Selector
Event Activate
For each line in customerGrid
if &select
&customer.Load( CustomerId )
&customer.CustomerStatus = Status.Active
&customer.Save()
Commit
endif
endfor
endevent
+
3. Eventos:
atributos sueltos
(fuera de for eachs)
Cmo determina GeneXus una tabla base a recorrer automticamente para cargar el grid del web
panel?
De existir algn atributo en por lo menos uno de los 3 lugares mencionados, GeneXus podr encontrar
tabla base. Para determinarla extrae los atributos encontrados all (parte fija del Form, en el Grid, tanto
en sus columnas como en las propiedades Order, Conditions o using Data Selector, y en los eventos
programados en el selector de Eventos, solamente considerando los atributos que estn sueltos dentro
del evento, es decir, no dentro de un comando for each de acceso a la base de datos), y determina la
mnima tabla extendida que los contiene. La tabla base de esa extendida, ser la recorrida
automticamente y cargada con el Load.
Observemos que solamente hemos programado el evento Load para tomar la decisin para cada lnea a
ser cargada en el grid, acerca de si se habilitar o no para la misma la variable &select que permitir al
usuario marcar el check box.
Importante: La forma de determinacin de la tabla base de un grid depender de si existe otro grid en el
web panel o es el nico. El resumen presentado aqu corresponde a un nico grid. En este caso se dice
que el propio Web panel tiene tabla base. Es la del grid. Cuando existan ms de un grid en el web
panel, esto ya no tendr sentido, y cada grid pasar a tener o no tabla base. Veremos la forma de
determinacin de las tablas bases en ese caso, cuando tratemos el caso de mltiples grids en un web
panel.
344
Web Panels
Aqu presentamos otro ejemplo, para observar un caso en el que surge naturalmente la necesidad de
implementar un grid sin tabla base.
El caso natural de implementacin de un grid con tabla base, es cuando se quiere cargar por cada
registro de una tabla, una lnea del grid (1 registro 1 lnea). Cuando el caso es que se quiere cargar
una lnea del grid como producto de recorrer varios registros de la base de datos (N registros 1 lnea),
como productos de clculos, etc., suele ser ms natural implementar el grid sin tabla base.
Este es el caso del ejemplo: no queremos cargar por cada factura una lnea, sino que queremos agrupar
facturas por fecha, y por cada grupo, cargar una lnea que sumariza sus Amount. Estamos hablando de
un corte de control. Si tuviramos que implementar un listado PDF en lugar de un web panel, sabramos
bien cmo programarlo (como lo hacemos arriba). Veamos cmo implementarlo con un web panel...
345
Web Panels
El objetivo del comando LOAD es agregar una lnea en un grid. Es necesario cuando el grid no tiene
tabla base, dado a que en ese caso no se agregar automticamente lnea alguna. El evento Load
ocurrir una vez, y si ste no se programa, el grid resultar vaco. Por tanto en este caso es
indispensable programarlo, de acuerdo a la lgica que corresponda. Una vez que se haya asignado
valor a cada variable, y se desee agregar una lnea al grid, deber ejecutarse el comando LOAD.
Solamente se puede especificar el comando LOAD dentro del evento Load del grid de un web panel.
Obsrvese que este caso es el que deja ms a cargo del analista la implementacin. Frente al caso de
grid con tabla base, en este GeneXus realiza muchas menos inferencias.
346
Web Panels
Refresh no es automtico!
En el caso de un grid sin tabla base, los filtros sobre los datos a mostrar son programados dentro del
cdigo que implementa la carga (el del Load). Aqu no habr refresh automtico. Esto es, cuando el
usuario modifique los valores de las variables que intervienen en los filtros, GeneXus no detectar que
debe volver a cargar el grid.
Para ello deber, por ejemplo, agregarse un botn asociado al evento Enter, o a un evento de usuario,
sin cdigo, debido a que solo lo necesitamos para que se produzca un Refresh, es decir para que se
vuelva al servidor a cargar el web panel.
Sobre los eventos disponibles y el orden en que se disparan, entraremos en lo que sigue.
347
Web Panels
Programacin dirigida por Eventos
Evento Start
Evento Refresh
Evento Load
Evento Enter
Eventos de Usuario
Evento TrackContext (no lo veremos en el curso)
Nota:
Refresh, Enter, de Usuario:
pueden asociarse a controles del form
a travs de propiedad OnClickEvent
En todo Web panel existen eventos del sistema que pueden programarse. Algunos ocurrirn siempre,
en cada ejecucin del web panel (como el Start, Refresh, Load), otros si se los declara y el usuario
realiza las acciones necesarias para provocarlos (Enter, definidos por el usuario, TrackContext).
Asimismo, casi todos los controles que aparecen en el form brindan la posibilidad de disparar un evento
cuando el usuario hace clic con el mouse sobre ellos (aparecen como hipervnculos en ejecucin); se
consigue de dos maneras distintas:
1. Editando las propiedades del control (F4), y definiendo un evento de usuario en la propiedad
OnClickEvent, o asocindole el evento Enter o el Refresh.
2. Dndole un nombre al control y en la seccin de Eventos programando:
Event nombreControl.click
Endevent
Con esta ltima alternativa no tendremos que definir un evento de usuario, sino que
estaremos programando el evento click del control. Lo mismo ocurre con los eventos DblClick,
RightClick, IsValid... (para cuando se hace doble clic, botn derecho, etc.).
Sobre los eventos asociados a las acciones sobre los controles (click, dblclick, drag, drop, etc.) no nos
explayaremos en el presente curso. En nuestro wiki encontrar informacin detallada, as como en el
Help de GeneXus.
Sobre el evento TrackContext solo mencionaremos que ser posible detectar cambios en el valor dado
a un control (grid, variable, etc.) y en ese caso disparar este evento para en base al valor modificado,
tomar una accin.
348
Web Panels
Evento Start
Es un evento del sistema, que ocurre automticamente siempre
que se hace Get o Post y es el primer evento que se ejecuta.
No se conocen valores de atributos, salvo los recibidos por
parmetro. Esto se debe a que an no se ha efectuado la
consulta.
Ejemplo: se puede utilizar para que un control del form no
aparezca visible, para cargar un bitmap, para asociarle un Link a
otro control, etc.:
Event Start
&var.Visible = 0
&Update = LoadBitmap("images/edit.gif")
newControl.Link = Link(TCustomer)
endevent
349
Web Panels
Evento Refresh Evento Load
Eventos del sistema, codificables, asociados a la carga del Web
Panel. Se ejecuta primero el Refresh y a continuacin siempre
el Load.
Si el grid tiene tabla base
Load se ejecuta N veces:
una por cada lnea
Cuando el web panel es con tabla base, al producirse el evento Refresh se accede a la base de datos, a
esa tabla base (la asociada al web panel), y se la recorre cargando los registros que cumplan las
condiciones (conditions del grid y generales). Ocurrir en ese proceso un evento Load por cada
registro en el que se est posicionado, inmediatamente antes de cargarlo. Esto nos permite realizar
alguna operacin que requiera de ese registro (y de su extendida), antes de efectivamente cargarlo en
el grid. Inmediatamente luego de ejecutado el cdigo asociado al evento Load, se cargar la lnea en el
grid y se pasar el puntero al siguiente registro de la tabla base, para realizar lo mismo (evento Load,
carga de la lnea). Este proceso se repetir hasta cargar todas las lneas del grid.
Si un web panel es sin tabla base, GeneXus no puede determinar automticamente una tabla de la base
de datos a recorrer para mostrar la informacin que se presenta en el form. En este caso en el form
solamente aparecen variables (y no atributos) y tambin ocurrirn los eventos Refresh y Load, slo que
el evento Load se ejecutar una nica vez, dado que no se estar posicionado en ningn registro de
ninguna tabla. Dentro de ese evento habr que codificar la carga, que podr requerir acceder a la base
de datos (ej: comando for each) o no (supngase que se desea cargar el grid con informacin obtenida
de recorrer un SDT collection, tras efectuar alguna transformacin sobre sus items... o cargar lneas en
el grid producto de clculos). El control de la carga del grid, queda aqu en manos del analista, utilizando
el comando Load. Este comando solo es vlido dentro del evento de igual nombre. Obsrvese cmo en
el caso de grid con tabla base, este comando se torna innecesario.
350
Web Panels
Refresh automtico
Solo vlido para Grid con tabla base
Estudiemos con ms detalle la propiedad Automatic Refresh que se encuentra a nivel del Web Panel
puede tomar los siguientes valores:
When variables in conditions change (valor por defecto): luego de provocarse automticamente el
refresh, se dispara el evento Load cargndose el grid segn los nuevos valores de las variables.
No: para que el contenido del grid se refresque luego de cambiar los filtros, el usuario debe realizar
una accin:
Si el grid es con tabla base:
Al presionar la tecla Enter, se dispara el Refresh de la pgina (no el cdigo del evento
Enter, aunque est programado).
351
Web Panels
Eventos Orden de disparo
GET: Cuando el Web Panel se abre.
Start
Refresh
Load
Start
Lectura de variables en pantalla
Evento enter o de usuario (click,
dblclick, etc., que produjo post)
Refresh
Load
Los eventos que se disparan y su orden depende de si se est abriendo el web panel (Get) o si ya
estaba abierto y se est efectuando una accin posterior, como presionar un botn (Post).
Arriba mostramos con ejemplos el caso general.
1a. vez: Start + Refresh + Load
N-sima vez: Start + Lectura de variables de pantalla + Evento que produjo el Post + Refresh + Load.
Este es el caso general... existe una excepcin...
352
Web Panels
Eventos Orden de disparo
Excepcin:
Algunos eventos de usuario deben ejecutarse en el Server pero para
otros no existe necesidad se ejecutarn solamente en el Cliente (sin
ejecutarse todos los otros eventos del server: Start, Refesh y Load).
Evitando roundtrips innecesarios al servidor, y reduciendo la cantidad de
datos que viajan de un lado a otro.
Ejemplo: un evento que cambia el estado de un control, no necesita
ejecutarse en el server.
Event UserEvent
&CustomerId.Visible = 0
endevent
Internamente GeneXus determina las entradas y salidas de cada evento. Si en sus entradas, se
requiere de acciones ejecutadas en el Server, entonces el evento se ejecutar en el Server. Por
ejemplo, si entre las entradas de un evento de usuario se encuentra alguna de las salidas del evento
Start (del server), entonces el evento de usuario se ejecutar en el Server.
Si el cdigo del evento no requiere que se ejecute en el servidor, entonces por performance, se
ejecutar en el cliente, como cdigo javascript.
De todas maneras el analista GeneXus no deber preocuparse de estos asuntos, dado que en todo
caso ser GeneXus quien tendr la inteligencia de resolver dnde ejecutar el evento.
353
Web Panels
Mltiples grids Grids paralelos
filtrar facturas
por da del
cliente
Aqu presentamos un ejemplo que rene los dos casos que venamos estudiando: el web panel
mostrado en ejecucin tiene dos grids paralelos: uno que muestra informacin de los clientes del
sistema, y otro que muestra facturas, totalizadas por da.
En nuestro caso, querremos adems relacionar los datos, de manera tal que si el usuario selecciona un
cliente, se le muestren solo las facturas de ese cliente. Incluso al establecer filtros de fechas, tambin
querremos que valgan para el cliente seleccionado (y no para todos los clientes).
Cuando un web panel contiene ms de un grid en su form, GeneXus no determina una nica tabla
base asociada al web panel, sino una tabla base asociada a cada grid.
Atributos que participan en la determinacin de la tabla base de cada grid:
Los incluidos en el grid (se tienen en cuenta tanto los atributos visibles como los no visibles)
Los referenciados en Order y Conditions locales al grid
A diferencia de lo que suceda para un web panel con un solo grid, en el caso de mltiples grids los
atributos de la parte fija del web panel no participan en la determinacin de la tabla base de ninguno de
ellos, pero debern pertenecer a la tabla extendida de alguno (para que sea posible inferir sus valores).
De no respetarse esto, al especificar al web panel, se mostrar en el listado de navegacin resultante,
una advertencia informando de esta situacin.
Los atributos utilizados en los eventos del web panel tampoco participan en la determinacin de la tabla
base de ninguno de los grids. Los atributos que se incluyan en los eventos fuera de comandos for each,
debern pertenecer a la tabla extendida de alguno de los grids (al igual que los de la parte fija).
354
Web Panels
Mltiples grids Grids paralelos
Event Start
&Customer.Visible = 0
endevent
Este web panel podra haberse implementado de varias maneras distintas, dando por resultado la
misma ejecucin.
La implementacin ms natural es la que podemos ver arriba: el primer grid tiene tabla base y el
segundo no. Pero podra haberse implementado al revs, con variables en el primer grid y teniendo que
realizar la carga de los clientes a mano en el Load, y atributos en el segundo grid, y algunas cosas ms
para lograr el corte de control, siendo un grid con tabla base. O cualquiera de las otras dos
combinaciones (ambos grids con tabla base, o ninguno con tabla base).
Lo importante es, una vez elegida la implementacin ms natural al caso, realizarla correctamente.
En cualquiera de los casos, aunque la informacin a cargar en un par de grids se encuentre relacionada
en la base de datos, GeneXus no asumir ninguna relacin entre los datos a la hora de cargar un grid y
el otro. Es anlogo al caso de un par de for eachs paralelos en el Source de un procedimiento.
Como puede verse arriba, al web panel en el que tenamos el grid con los clientes, le hemos agregado
la parte de visualizacin de facturas por fecha que habamos implementado en web panel aparte. Pero
no alcanza con simplemente unir ambos web panels... para poder relacionar las cargas de los grids,
deberemos agregar cierta lgica. En nuestro caso deseamos que una vez que se seleccione un cliente
del primer grid, las facturas que se carguen en el segundo no sean las de todos los clientes, sino las del
seleccionado.
Para ello debimos hacer dos cosas: agregar una variable &CustomerId para almacenar el id del cliente
seleccionado al presionar Select customer, y luego agregar un filtro por el valor de esa variable cuando
se carga el grid de Invoices. Asimismo tuvimos necesariamente que colocar esa variable en el form para
que todo funcione como esperamos... y la razn la encontraremos en el anlisis que sigue.
355
Web Panels
Mltiples grids Grids paralelos
1. ejecucin
Start oculta &customerId
Refresh
customerGrid.Refresh
customerGrid.Load
customerGrid.Load
....
invoicesGrid.Refresh
invoicesGrid.Load
Analicemos lo que sucede cuando se ejecuta este web panel por primera vez.
Primero se ejecuta el evento Start, que en nuestro caso oculta la variable &CustomerId.
Luego, como puede apreciarse en la imagen, se produce un evento Refresh genrico, luego del cul se
producirn las cargas de todos y cada uno de los grids que se encuentren en el web panel, de izquierda
a derecha de arriba a abajo.
Por cada uno ocurrir un evento Refresh propio y el evento Load (N veces si el grid tiene tabla base, 1
sola si no la tiene).
Obsrvese que en nuestro caso, el grid de clientes tiene condiciones para cargarse, por las variables de
filtro &customerName y &countryName, pero al estar vacas no aplican (dado que ambas clusulas
condicionales tienen when not &var.IsEmpty())
El segundo grid es sin tabla base, pero como ya vimos, el evento Load ejecutaba un for each con
clusulas where, por tanto se cargarn solo aquellas lneas para las que se cumplan sus condiciones.
Estas son tres:
where InvoiceDate >= &startDate when not &startDate.IsEmpty()
where InvoiceDate <= &endDate when not &endDate.IsEmpty()
where CustomerId = &customerId when not &customerId.IsEmpty()
Obsrvese que en esta primera ejecucin &customerId estar vaco, por lo que no se aplicar este filtro
y se cargarn todas las facturas por da, de todos los clientes.
356
Web Panels
Mltiples grids Grids paralelos
2. ejecucin Seleccionar un cliente:
Start oculta &customerId
Lectura de variables de pantalla
Evento que produjo post
Event Select customer
&CustomerId = CustomerId
endevent
Refresh
customerGrid.Refresh
customerGrid.Load
customerGrid.Load
....
invoicesGrid.Refresh
invoicesGrid.Load
Luego el usuario selecciona del grid el cliente correspondiente a la segunda lnea y presiona el botn
Select customer.
Se detecta una accin, y se realiza un post al servidor, quien ejecuta el Start (ocultando la variable),
luego lee las variables en pantalla (&customerId por ahora est vaca, pero no slo son consideradas
variables de pantalla las variables definidas, sino, por ejemplo, la informacin completa de la lnea
seleccionada por el usuario con el mouse, entre ella, el valor de CustomerId, columna del grid), luego
ejecuta el cdigo del evento que produjo el post, en nuestro caso, Select customer. Aqu la variable
&customerId toma el valor del CustomerId de la lnea elegida. Luego se produce el Refresh general que
dispara el Refresh y Load de cada grid.
Por tanto, cada grid se carga ejecutando las conditions. El primero se carga igual que antes, porque
ninguna de sus conditions ha variado. El segundo, ahora s tiene un valor para &customerId, por lo que
se mostrarn solamente las facturas del cliente.
Uno podra preguntarse por qu se tuvo la necesidad de colocar la variable oculta en el form. Por qu
simplemente no poda usrsela como variable dentro del programa, sin necesidad de colocarla y hacerla
invisible. Con esta segunda ejecucin todava no podemos contestar la pregunta. De hecho, si se
analiza, puede verse fcilmente que hubisemos obtenido el mismo comportamiento si slo le
asignbamos valor a la variable en el Select Customer sin colocarla en el form.
La razn surgir claramente con la siguiente ejecucin...
357
Web Panels
Mltiples grids Grids paralelos
3. ejecucin Filtrar facturas para el
cliente seleccionado
Start
Lectura de variables de pantalla
&customerId invisible
Ahora el usuario ya tiene seleccionado el segundo cliente, y lo que desea es filtrar sus facturas por
fecha (no quiere visualizarlas todas).
Para ello especifica los filtros de fecha, y presiona el botn Search, que producir un post al servidor.
Entonces se ejecutar el Start con su cdigo, luego se leern las variables de pantalla: aqu est la
razn de haber colocado &customerId en el form. Se leer entonces el valor de &customerId, que
permanecer incambiado hasta tanto el usuario no vuelva a seleccionar otro cliente del grid y presionar
el botn Select customer... esta variable presente en el form, es la forma de mantener la memoria entre
ejecuciones.
Recurdese que cada vez que se hace un post al servidor, es una nueva ejecucin del web panel, por lo
que las variables comienzan nuevamente vacas. Es por ello que el segundo paso: Lectura de variables
de pantalla es fundamental.
Ahora s, siguiendo con el ejemplo, se lee de pantalla la variable &customerId invisible, junto con las
variables visibles &startDate y &endDate.
Y luego, como siempre, se ejecuta la carga (Refresh genrico + Refresh y Load de cada grid).
Han cambiado las condiciones del for each que carga el segundo grid, por lo que ahora aparecern
solamente las facturas del segundo cliente, entre las fechas estipuladas por el usuario.
Si ahora el usuario quiere cambiar de cliente, para ver sus facturas, lo seleccionar del grid de clientes y
presionando Select Customer, el proceso volver a empezar como vimos en la 2da. ejecucin.
Y cmo se vuelve a trabajar con las facturas de todos los clientes y no con las de uno dado?
Piense qu pasar si el usuario no selecciona ningn cliente del grid con el mouse, pero presiona
Select Customer. El valor de la variable &CustomerId quedar vaco, pues CustomerId no tendr valor.
Por este motivo, al botn Select Customer podramos haberle llamado Select/Unselect.
358
Web Panels
Grid - Propiedades
Paginado automtico: GeneXus realiza un paginado automtico si
la propiedad Rows tiene un valor distinto de 0.
Los botones que se insertan dependen de la cantidad de registros a mostrar y la cantidad de lneas del
grid.
359
Web Panels
Grid Ordenamiento automtico de las columnas
Las columnas pueden ser ordenadas sin necesidad de programar ningn
cdigo adicional: clic sobre el ttulo de la columna.
Esta funcionalidad
es vlida para grids
en transacciones y
en web panels.
360
Web Panels
Tipos de grids
Grid estndar: Datos repetitivos en
formato fijo (filas y columnas)
361
Web Panels
Mltiples grids Grids anidados
Ejemplo: Desplegar todos los pases con sus respectivos clientes, y cantidad de
clientes.
Trn Country
{
CountryId*
CountryName
CountryFlag
Grid2: estndar
Trn Customer
Tabla base Grid1:
COUNTRY
{
CustomerId*
CustomerName
CustomerAddress
CountryId
CountryName
}
Este caso de grids anidados es como el de for eachs anidados en el caso de un procedimiento: esto es,
aqu s se relacionan las cargas, y se cargarn por tanto en el Grid2, todos los clientes pertenecientes al
pas cargado en el Grid1 en cada oportunidad.
De hecho, el orden de ejecucin de los eventos estar anidado:
Refresh (genrico)
Grid1.Refresh
Grid1.Load carga de un pas
Grid2.Refresh
Grid2.Load carga de cliente del pas
Grid2.Load carga de cliente del pas
Grid2.Load carga de cliente del pas
Grid1.Load carga del siguiente pas
Grid2.Refresh
Grid2.Load carga de cliente del pas
Grid2.Load carga de cliente del pas
Grid2.Load carga de cliente del pas
.....
362
Web Panels
Grid Free Style
(Ejemplo: Continuacin)
Propiedades
Grid Free Style
363
Web Panels
Tipos
Tipos de Web panels
Component
Web Page
Master Page
Propiedad Type
Los objetos web pueden ser definidos con tres tipos diferentes, configurable en la propiedad Type del
objeto. Para un web panel podr tomar uno de los valores:
Component: (transaccin web panel, que a partir de aqu podr ser incluido en otro web object
transaccin o web panel)
Web Page (es decir, el objeto ser una transaccin web panel tal como hemos trabajado hasta el
momento)
Master Page
A continuacin introduciremos el Web Panel tipo: Component y luego volveremos sobre el Master
Page pero no lo veremos en profundidad en este curso.
364
Web Panel
Web Component
Ya tenamos programado un
web panel CustomerView
que mostraba los datos del
cliente Reutilicmoslo
Un component es un
web panel pero que se va
a ejecutar dentro de otro.
365
Web Panels
Web Component
366
Web Panels
Web Components
Ejemplo: Crear un nuevo tab en la instancia de Pattern Work With Countries,
mostrando los clientes por cada pas.
367
Web Panels
Web Components
368
Web Panels
Master Pages
El otro tipo de Web Panel que ya vimos es la Master Page, que
centraliza layout y comportamiento comn, en un solo objeto y
permite reutilizarlo en todo otro objeto sin tener que programar.
control dentro
del que se
cargarn las
pginas
Creadas automticamente
con la KB
Tener un look & feel consistente es hoy en da un deber de toda aplicacin Web.
Crear y mantener cada pgina de una aplicacin Web asegurando la consistencia con el resto del sitio toma
gran tiempo de programacin.
Al crear una base de conocimiento, GeneXus X crear tambin dos objetos de tipo Master Page:
ApplMasterPage: Para la aplicacin.
PromptMasterPage: Para los prompts.
Se crear un web panel, ApplMasterPage categorizado como Master Page con todo lo que sea el Layout y
comportamiento comn a todas las pginas del sitio, y en el mismo se dejar un espacio para cargar en cada
oportunidad la pgina que corresponda (el contenido variable del sitio). Corresponde al control especial
ContentPlaceholder. Las pginas web que implementan el contenido variable, se implementan como Web
Panels o Web Transactions comunes y corrientes (es decir de tipo Web Page), y se asocian a la Master Page
(a travs de la propiedad de igual nombre), de manera que cada vez que se ejecuten, se carguen con ese
contexto. Abra cualquier objeto GeneXus con form (transaccin o web panel) creado en una KB, y vea el valor
de la propiedad Master Page.
Las Master Pages proveen una forma de centralizar el layout y el comportamiento comn en un solo objeto y
reutilizarlo en todo otro objeto sin tener que programar. Esto significa que la modificacin de alguna parte del
layout o del comportamiento comn es tan fcil como modificarla en un nico objeto y listo!.
En una misma base de conocimiento se pueden definir tantas Master Pages como se desee.
369
Gxflow
370
GXFLOW
Qu es unworkflow?
Unsetdetareas ordenadas enuna secuencia determinada,que defineun
proceso enelcual las situaciones sonresueltas obien manualmente o
automticamente.
Ejemplo
En el ejemplo se est mostrando un workflow que se sigue en una empresa que vende mercadera al
por mayor.
Se pueden observar claramente las tareas consecutivas que se siguen para llevar a cabo el proceso de
venta.
371
GXFLOW
372
GXFLOW
373
GXFLOW
374
GXFLOW
375
GXFLOW
376
GXFLOW
TAREA / ACTIVIDAD
INTERACTIVA
ARRASTRANDO ESTOS
SMBOLOS SE
CONFECCIONA
DIAGRAMA
TAMBIN SE PUEDE
ARRASTRAR AL DIAGRAMA
TAREA / ACTIVIDAD
INTERACTIVA DESDE
FOLDER VIEW
Si desde Folder View se arrastra un objeto transaccin o web panel al diagrama, se estar agregando
una tarea / actividad interactiva al flujo, y la misma ya quedar con dicho objeto asociado para la
etapa de ejecucin. Tambin dicha tarea / actividad interactiva agregada al diagrama, quedar
automticamente nominada con el mismo nombre que la transaccin o web panel que fue arrastrado.
Si en cambio se agrega una tarea/actividad interactiva al diagrama arrastrando el smbolo
correspondiente desde la toolbox disponible para confeccionar diagramas de procesos de negocios,
luego ser necesario asociar a dicha tarea un objeto transaccin o web panel definido en la KB.
Para ello, simplemente despus de haber agregado la tarea en el diagrama y tenindola seleccionada,
habr que editar sus propiedades (F4 para abrir el dilogo de propiedades) y completar la propiedad
Web Application con el objeto que corresponda, as como la propiedad Name con el nombre que se le
quiera dar a la tarea/actividad interactiva.
377
GXFLOW
Descripcin desmbolos
INICIO DE PROCESO
ACTIVIDAD/TAREA INTERACTIVA
ACTIVIDAD/TAREA BATCH
EN ESTE PROCESO QUE SE EST MODELANDO,
OTRO PROCESO ES REUTILIZABLE COMO
SUBRPROCESO
CONDICIN PARA EVALUAR Y SEGN
RESULTADO, SE SEGUIR UNA RUTA U OTRA
VIENEN VARIAS RUTAS HASTA ESTE SMBOLO Y RECIN
AL LLEGAR TODAS A ESTE PUNTO, EL FLUJO CONTINA
FIN DE PROCESO
No se describirn todos los smbolos disponibles en la toolbox de workflow, sino los smbolos bsicos
que debemos conocer en un principio.
Smbolo: Condicin
Cuando se est modelando un diagrama de proceso y en determinada parte del flujo de actividades se
necesita evaluar una condicin para que dependiendo de si se cumple o no, se siga con cierto flujo de
actividades u otro, es que contamos con el smbolo de condicin.
378
Bastar con agregar un smbolo de condicin (rombo verde) al diagrama (conectado desde la
actividad previa) y a partir del rombo podrn salir N rutas (que sern de color verde tambin).
Cada una de estas rutas verdes que salgan desde un rombo de condicin, deber tener
asociada una condicin a ser evaluada (haciendo doble clic en cada ruta verde, se abrir un
editor para ingresar su condicin asociada); y en tiempo de ejecucin del diagrama, como
veremos ms adelante, cuando se llegue a la condicin en la ejecucin del proceso,
dependiendo de cul de las evaluaciones resulte verdadera se continuar con la ejecucin de
una ruta y su flujo de actividades que le sigue, u otra.
En breve veremos ejemplos de definicin de condiciones (sintaxis y posibilidades).
379
GXFLOW
Aqu vemos que hemos ido confeccionando el diagrama de proceso que creamos. Le hemos agregado
tareas interactivas y una condicin.
Vemos que con doble clic en las rutas verdes que salen de la condicin, se abre el editor de condiciones
para editar cada condicin (as en caso de cumplirse una u otra se seguir con cierto flujo de
actividades u otro).
En lo que sigue veremos el concepto de Datos Relevantes que es fundamental para comprender qu
informacin podemos involucrar en las condiciones.
380
GXFLOW
381
GXFLOW
Tambin definiremos
veremos...
datos
relevantes
explcitamente,
como
Para los datos relevantes que se definen automticamente con igual nombre y tipo que las claves
primarias de las transacciones (como en este ejemplo: InvoiceId), hay una correspondencia automtica
entre el dato relevante y el atributo PK.
Esto es, cuando modelamos el diagrama el dato relevante es el dato global conocido en ese contexto y
en los objetos GeneXus que desarrollamos asociados a las actividades del diagrama recibimos en
parm al atributo PK (tratndose de la misma informacin o bien en el contexto del diagrama, o en el
contexto del desarrollo de la funcionalidad respectivamente). En otras palabras hay un mapeo
automtico entre el dato relevante de igual nombre y tipo al de un atributo clave primaria y dicho atributo
clave primaria.
Si bien la mayora de Datos Relevantes en un diagrama de proceso suelen corresponderse con claves
primarias, tambin hay casos en los que surge la necesidad de definir explcitamente otros datos
relevantes. A continuacin veremos ejemplos.
382
GXFLOW
thor
l Au
Pane
b
e
W
n
izatio
Parm(InvoiceId);
Inicialmente hemos explicado que cuando trabajamos en GeneXus con workflow, realizamos los
siguientes pasos bsicamente:
Crear objetos GeneXus
Crear diagramas de procesos de negocios
Asociar objetos GeneXus a diagramas de procesos de negocios
Ejecutar proceso
As es que venimos confeccionando un diagrama de proceso en nuestra KB; tenamos previamente
definidos algunos objetos GeneXus que hemos arrastrado al diagrama, y vamos desarrollando otros
objetos e incorporndolos al diagrama tambin. Ms adelante veremos como asignar roles a las
diferentes actividades del diagrama. Por ahora la idea es que contamos en la KB con una transaccin
Invoice, la cual fue arrastrada al diagrama como primer actividad interactiva del proceso y ms
adelante definiremos que esta tarea interactiva podr ser ejecutada por las vendedoras de la empresa.
Cuando una vendedora ingrese una venta (a travs de la transaccin Invoice), entrar el cliente, la
mercadera solicitada, las cantidades, la forma de pago solicitada por el cliente, grabar la venta con un
nmero interno (no el nro de factura formal) y ah terminar la primer actividad. Luego esa venta deber
ser evaluada por un supervisor (quien evaluar de qu cliente se trata, el monto, la forma de pago), y el
supervisor deber aceptar o denegar la venta. Esta segunda actividad interactiva del proceso fue
agregada al diagrama arrastrando el web panel Authorization.
Entonces, a nivel del diagrama de proceso contamos con el dato relevante InvoiceId (de igual nombre y
tipo de dato que el atributo InvoiceId), lo cual significa que dicho dato se conoce a lo largo de todo el
flujo de actividades. Y en lo que se refiere a los objetos GeneXus relacionados al diagrama, el web
panel Authorization implementa la 2da actividad del proceso y recibe por parmetro al atributo
InvoiceId. En el form del web panel Authorization se visualizarn los datos de la factura, el lmite de
crdito y saldo de lmite de crdito del cliente y estar la posibilidad de ver la historia de facturas
anteriores del cliente. Este web panel ofrecer al supervisor 2 botones: Authorize y Refuse.
383
Vale explicar que cuando trabajamos con workflow en GeneXus, en el cdigo de los objetos ya no
pondremos invocaciones de un objeto a otro. En cambio, en los diagramas de procesos que
confeccionamos ya quedan implcitas las invocaciones entre actividades consecutivas.
Ms adelante veremos que en la etapa de ejecucin, procederemos a ejecutar una aplicacin que nos
ofrecer crear instancias de los procesos que hemos definido (por ejemplo se podrn crear N instancias
del proceso de venta definido). Al crear una nueva instancia de proceso, comenzar la ejecucin de la
primer actividad (se presentar la trn Invoice para ello, y si definimos roles, se validar que en particular
sea una vendedora quien realice esta actividad). Una vez finalizada la primer actividad, seguir la
segunda actividad (para ser efectuada por el rol que corresponda, que en nuestro ejemplo es un
supervisor) y as sucesivamente se irn finalizando actividades de la instancia del proceso y ejecutando
las siguientes actividades hasta concluir dicha instancia de proceso.
De modo que no codificamos ms calls en los objetos GeneXus, y de necesitar cambiar el orden de
precedencias de las actividades en un proceso, o agregar o quitar actividades, as como cambiar las
condiciones de ejecucin de las actividades, lo reflejamos en el diagrama de proceso sin tocar el cdigo
de los objetos.
Algo a hacer notar es que si bien no definimos calls en el cdigo mismo de los objetos, s definimos regla
parm en los objetos GeneXus que participan en un diagrama de proceso. Esto es porque los objetos son
invocados -si bien con otro esquema de trabajo del que conocamos- y necesitan pasarse la informacin
necesaria as es que suelen recibir por parmetro los atributos claves primarias que son anlogas a los
datos relevantes en el diagrama de proceso (y que hay una correspondencia entre estos conceptos).
Una vez hechas estas explicaciones, seguiremos estudiando paso a paso la implementacin de la
segunda actividad del proceso que venimos confeccionando. El web panel Authorization recibe por
parmetro al atributo InvoiceId, muestra en su form informacin para la toma de desicin de la
autorizacin o denegacin y para ello contiene 2 botones Authorize y Refuse respectivamente.
Si nuestro objetivo es cargar una variable con valor 1 en el evento Authorize y con valor 0 en el evento
Refuse, y queremos que el valor asignado se vea en el diagrama de proceso, bastar con realizar lo
siguiente:
1) En el tab Relevant Data del diagrama de proceso, habr que crear un dato relevante (por ejemplo de
nombre: InvoiceAuthorized) de tipo Numeric.
2) En el web panel "Authorization habr que leer el dato relevante y cargarlo en cada evento del web
panel, as:
Siendo:
&wfAuthoriz: una variable definida en el web panel, de tipo de datos es: WorkflowApplicationData
&wfProcessInstance: una variable definida en el web panel, de tipo de datos: WorkflowProcessInstance
384
GXFLOW
1)
2)
En wbp Authorization
defimos 2 variables
de tipos de datos
WorkflowApplicationData
y WorkflowProcessInstance
para leer y cargar dato
relevante
De modo que hemos definido un dato relevante en el diagrama de proceso (de nombre
InvoiceAuthorized) y luego en el web panel Authorization se lee el dato relevante en variable
&wfAuthoriz de tipo WorkflowApplicationData. El tipo de datos WorkflowApplicationData viene a
significar dato relevante.
Tambin hemos definido en el web panel una segunda variable de tipo WorkflowProcessInstance. El
tipo de datos WorkflowProcessInstance viene a significar instancia de proceso. O sea que si
analizamos la primer lnea codificada en cualquiera de los 2 eventos, estamos recuperando en la
variable &wfAuthoriz (de tipo dato relevante) el valor del dato relevante de nombre InvoiceAuthorized
(entre comillas va el nombre del dato relevante tal como se ha definido en el diagrama de proceso)
perteneciente a la instancia del proceso que se est ejecutando.
Luego en la segunda lnea codificada en ambos eventos, se est asignando a la variable &wfAuthoriz
(de tipo dato relevante) el valor 0 o 1 segn corresponda (utilizando la propiedad Numeric del tipo
de dato WorkflowApplicationData, por estar asignando un valor nmerico).
Por ltimo en cada evento se hace return, porque ya se ha recuperado el valor del dato relevante, se le
ha cargado el valor deseado y se desea culminar con la ejecucin de esta actividad.
De esta manera entonces leemos y cargamos datos relevantes en los objetos GeneXus asociados a las
actividades de un diagrama de proceso, empleando tipos de datos workflow, propiedades y mtodos.
Sin embargo para datos relevantes con igual nombre y tipo que las claves primarias, esto no es
necesario (sino que se reciben por parm los atributos primarios directamente y ya hay mapeo
automtico con el dato relevante correspondiente).
385
GXFLOW
Observe que en cada ruta verde que sale del rombo de condicin, se evala el valor del dato relevante
&InvoiceAuthorized.
Si bien cuando definimos el nombre del dato relevante no incluimos el & (amperson), el dilogo de
definicin de datos relevantes muestra claramente un cono &, dando la pauta de que se trata de
variables:
De modo que para referirnos a un dato relevante en el flujo, lo referenciamos con & como se puede
observar en las 2 imgenes capturadas correspondientes al editor de condiciones. Sin embargo para
datos relevantes con igual nombre y tipo que las claves primarias, es posible referenciar tanto el dato
relevante (con &) como el atributo clave primaria directamente.
386
GXFLOW
Se quiere definir atributo InvoiceAuthorized en trn Invoice y grabar en cada invoice si fue
autorizada o no..
2)
En web panel Authorization se invoca proc en cada evento, que graba 1 o 0 en atributo
InvoiceAuthorized
3)
EVALUAMOS ATRIBUTO
(NO DATO RELEVANTE)
Con esta solucin, no tenemos necesidad de definir Dato Relevante InvoiceAuthorized , ya que tenemos
en un atributo la informacin de si la invoice fue autorizada / denegada y en el flujo se pueden inferir
atributos a travs de claves primarias, y evaluar directamente atributos.
387
GXFLOW
Definicin deroles
1)
DEFINICIN
DE ROLES EN
LA KB
2)
ASIGNACIN
DE ROLES
A ACTIVIDADES
EN DIAGRAMA
388
GXFLOW
389
GXFLOW
Pasosparaejecutar:
Save All
Build All
(Se solicitarn datos de Enviroment)
Run del Diagrama de Proceso
390
GXFLOW
Ejecucin:
Lgicamente la modalidad Prototyper est orientada a la etapa de prototipacin. Y la modalidad FullClient a etapa de produccin.
En etapa de prototipacin no nos interesa probar la seguridad, motivo por el cual al ejecutar la
aplicacin en modalidad Prototyper inicialmente se limpian todas las instancias de pruebas anteriores y
se permiten ejecutar todas las actividades sin controlar roles.
Al ejecutar la aplicacin en modalidad Full-Client en cambio, no se aborta nada inicialmente y se
requiere crear usuarios (para login) cada uno de ellos con la lista de roles que le corresponda, ya que en
este caso s la seguridad se controlar.
391
Manejo de versiones
392
Manejo de Versiones
Eldesarrollodesoftwareesuntrabajoenequipoyciertogrado de
confusinesinevitable.
Qu pas con el
arreglo de la
semana pasada?
No puedo
reproducir el
error en esta
versin!
La aplicacin en
ejecucin no es
compatible con
el cdigo fuente
Realmente
estamos
trabajando en
la ltima
versin?
Este
programa
ayer
funcionaba!
393
Manejo de Versiones
Conclusin:
Elciclodedesarrolloesunprocesodinmicoquerequiere
controldeloscambiosrealizadosalosobjetosdelproyecto.
Senecesita:
Marcarhitoseneldesarrollodelaaplicacin
Tenerlneasdedesarrolloparalelas
Administrarelciclodevidadelaaplicacin(SCM)
. . .
KB
Versin 1
Versin 2
Versin N
394
Manejo de Versiones
Solucin:Manejodeversionesdelaaplicacin
1.1.1
APP
APP
1.0
1.1
1.2
1.0.1
1.1.2
2.0
1.0.2
2.1
1.0.3
Se comienza el desarrollo siguiendo una lnea principal de desarrollo (lnea del medio Trunk), lugar donde se
agregan las funcionalidades requeridas y se utilizan prototipos para probarlas .
En determinados momentos de este ciclo surge la necesidad de establecer un checkpoint en el proceso, ya sea por la
liberacin de una versin, la entrega de una versin a un cliente, la necesidad de congelar un determinado estado de
una aplicacin, etc. Entonces lo que hacemos es congelar el producto en ese momento creando por ejemplo la
versin 1.0 que se la entregamos a un cliente y se contina el proceso de desarrollo principal.
En determinado momento surge la necesidad de realizar correcciones sobre la versin entregada al cliente (1.0) por
lo que es necesario abrir una nueva lnea de desarrollo para incluir estas correcciones sobre lo que era la versin 1.0
sin afectar la lnea de desarrollo principal que sigui creciendo desde el momento de la congelacin de la versin 1.0.
Entonces se crea lo que se conoce como Developmen Version o branch, que es simplemente una nueva lnea de
desarrollo paralela a la principal.
Luego durante el transcurso del proyecto vuelven a aparecer requerimientos de este tipo, ya sea de determinacin de
checkpoints como la necesidad de abrir nuevas lneas de desarrollo, entonces por ejemplo creamos la versin 1.1, o
la 1.0.1 que vendra a ser un congelado de la lnea de desarrollo abierta a partir de la versin 1.0 y as sucesivamente
hasta tener por ejemplo la situacin planteada en el diagrama.
Estas situaciones forman parte de la operativa normal en el desarrollo de una aplicacin y es necesario administrar
fcilmente este proceso.
Para ello se introduce el concepto de Manejo de Versiones. Las versiones se clasifican en:
Development Versions, representan las lneas de desarrollo de la aplicacin las cuales son independientes entre si,
existe una lnea principal y varias paralelas, la principal vendra a ser lo que se conoce como Trunk y las dems
seran lo que en SCM se conoce como Branches
Frozen Versions (tambin conocidas como Labels en SCM), representan los congelados creados en determinados
momentos del proceso sobre las DV para determinar ciertos checkpoints (liberacin de versin, entrega a cliente,
congelar estado, etc.)
395
Manejo de Versiones
Solucin:Manejodeversionesdelaaplicacin
Development Version
1.1.1
APP
APP
1.0
1.1
1.2
1.1.2
2.0
2.1
1.0.1
1.0.2
1.0.3
Development Version
Frozen Versions
Se comienza el desarrollo siguiendo una lnea principal de desarrollo (lnea del medio Trunk), lugar donde se
agregan las funcionalidades requeridas y se utilizan prototipos para probarlas .
En determinados momentos de este ciclo surge la necesidad de establecer un checkpoint en el proceso, ya sea por la
liberacin de una versin, la entrega de una versin a un cliente, la necesidad de congelar un determinado estado de
una aplicacin, etc. Entonces lo que hacemos es congelar el producto en ese momento creando por ejemplo la
versin 1.0 que se la entregamos a un cliente y se contina el proceso de desarrollo principal.
En determinado momento surge la necesidad de realizar correcciones sobre la versin entregada al cliente (1.0) por
lo que es necesario abrir una nueva lnea de desarrollo para incluir estas correcciones sobre lo que era la versin 1.0
sin afectar la lnea de desarrollo principal que sigui creciendo desde el momento de la congelacin de la versin 1.0.
Entonces se crea lo que se conoce como Developmen Version o branch, que es simplemente una nueva lnea de
desarrollo paralela a la principal.
Luego durante el transcurso del proyecto vuelven a aparecer requerimientos de este tipo, ya sea de determinacin de
checkpoints como la necesidad de abrir nuevas lneas de desarrollo, entonces por ejemplo creamos la versin 1.1, o
la 1.0.1 que vendra a ser un congelado de la lnea de desarrollo abierta a partir de la versin 1.0 y as sucesivamente
hasta tener por ejemplo la situacin planteada en el diagrama.
Estas situaciones forman parte de la operativa normal en el desarrollo de una aplicacin y es necesario administrar
fcilmente este proceso.
Para ello se introduce el concepto de Manejo de Versiones. Las versiones se clasifican en:
Development Versions, representan las lneas de desarrollo de la aplicacin las cuales son independientes entre si,
existe una lnea principal y varias paralelas, la principal vendra a ser lo que se conoce como Trunk y las dems
seran lo que en SCM se conoce como Branches
Frozen Versions (tambin conocidas como Labels en SCM), representan los congelados creados en determinados
momentos del proceso sobre las DV para determinar ciertos checkpoints (liberacin de versin, entrega a cliente,
congelar estado, etc.)
396
Manejo de Versiones
Development Version:(Branch)Lneadedesarrollodela
aplicacin.Puedenhabervariaslneasquetranscurranparalelas.
Development Version
APP
APP
1.0
1.1.1
1.1
1.2
1.1.2
2.0
2.1
1.0.2
1.0.3
Development Version
Las development version son las lneas de desarrollo de la aplicacin, es decir el lugar donde
efectivamente creamos y modificamos la aplicacin.
En el ciclo de vida de una aplicacin participa una lnea de desarrollo principal, es decir, donde
comienza el proceso de desarrollo de la aplicacin y en la cual normalmente se van a estar haciendo las
modificaciones requeridas en el avance del proyecto. En SCM esta lnea de desarrollo se conoce con el
nombre de Trunk.
Adems de esta lnea principal podrn existir una o varias lneas de desarrollo secundarias, totalmente
independientes de la lnea principal e independientes entre si. En SCM estas lneas de desarrollo
secundarias se conocen como Branches y son usadas en general para realizar correcciones o
pequeos agregados sobre versiones congeladas o liberadas de la aplicacin, o para liberar una versin
especial para un cliente.
El desarrollo en cada una de estas development version es independiente, teniendo cada versin sus
propios objetos, su propia base de datos, ambientes para generar la aplicacin, etc.
Una Development Version, es entonces, una copia de la KB editable e independiente.
397
Manejo de Versiones
Frozen Version:Versinnomodificable,esunafoto dela
aplicacinenunmomentodado.
1.1.1
APP
APP
1.0
1.1
1.2
1.0.1
1.1.2
2.0
1.0.2
2.1
1.0.3
Frozen Versions
Una Frozen Version permite almacenar en forma esttica momentos especiales de la KB. Es el
elemento que utilizamos para marcar distintos hitos en el proceso, como por ejemplo el cierre de una
versin para liberarla a los clientes.
Se obtiene a partir de una versin en desarrollo (development version), congelndola para obtener una
foto en un determinado momento.
La versin obtenida es Read Only, es decir que objetos de la misma no podrn ser modificados, ni
tampoco sus propiedades. S ser posible realizar acciones relacionadas con la generacin de la
aplicacin, como por ejemplo la creacin de la base de datos o la regeneracin de los programas.
Cuando congelamos una versin es porque determinamos que la misma est en un estado consistente
y sera conveniente guardar dicho estado. Por ejemplo, congelamos una version X para drsela a los
clientes, en determinado momento, mientras se contina con el proceso de desarrollo, un nuevo cliente
requiere de la aplicacin, entonces lo que hacemos es generar la misma en la version X, que sabemos
tiene un estado correcto y se la instalamos al nuevo cliente.
Los objetos si bien no pueden ser modificados, pueden ser abiertos para distintas consultas o para
realizar comparaciones con otras versiones de la aplicacin.
398
Manejo de Versiones
Ejemplodeversionado:Implementacinpasoapaso
Variaciones debido a arreglos o cambios en
requerimientos
APP
APP
..
Development
Version
principal
(Trunk)
Partimos del nodo raz del rbol de versiones, el cual se crea al crear la KB.
La aplicacin va sufriendo cambios a medida que transcurre el ciclo de desarrollo. La lnea de desarrollo
principal es donde se implementan las funcionalidades requeridas y donde se hace el prototipado.
Esta lnea de desarrollo generalmente coincide con el Trunk, o sea con la rama principal del rbol de
versionado. Es una Development Version creada por defecto al crearse la KB.
A medida que se van haciendo modificaciones a la aplicacin, la misma va cambiando a lo largo del
tiempo.
399
Manejo de Versiones
Paraverelrboldeversiones,abrimoslaventanaKnowledge Base
Versions (View/Versions):
400
Manejo de Versiones
Surgelanecesidaddecongelar versiones,parafijarhitosenel
proyecto.ParaesocreamosFrozen Versions (copiadeslo
lecturadelaaplicacin).
..
APP
APP
1.0
1.0
Development Version
principal (Trunk)
Frozen
Version 1.0
401
Manejo de Versiones
Cmocongelamos unaDevelopment Version,paracrearuna
Frozen Version?
402
Manejo de Versiones
AhoraqueremosponerlaaplicacinenProduccin.Paraesopartir
deunaFrozen Version 1.1creamosunaDevelopment Version
Release 1.
..
APP
APP
1.0
1.0
Development Version
principal (Trunk)
1.1
1.1
Release1
Release1
Development
Version para
Produccin
403
Manejo de Versiones
CreamoslaFrozen Version 1.1comovimosanteriormente
Frozen
Version
1.1
Ntese que las Frozen Version ms nuevas, se muestran ms arriba en el rbol de versiones.
404
Manejo de Versiones
DamosbotnderechosobrelaFrozen Version 1.1yseleccionamos
New Version paracrearlaDevelopment Version Release 1.
Development
Version
Release1
El tiempo que se demora en crear una nueva Development Version es proporcional al tamao de la KB.
405
Manejo de Versiones
TambinpodemoscrearnuevasFrozen Versions tantoenlarama
deldesarrolloprincipalcomoenlaramadeProduccin.
..
KB1
KB1
1.0
1.0
Produccin
1.1
1.1
1.2
1.2
Trunk
2.0
2.0
2.1
2.1
Release1
Release1
1.1.1
1.1.1
1.1.2
1.1.2
Frozen Versions
de Produccin
Como las lneas de desarrollo del Trunk (Desarrollo) y de Relase 1 (Produccin) son paralelas, los
cambios en una no afecta a la otra.
Ambas versiones son entonces totalmente independientes y podemos requerir congelarlas por
diferentes motivos. Por ejemplo, en el caso de la rama de Produccin, para fijar un estado luego de
ciertos arreglos que tuvimos que hacer.
De acuerdo a la metodologa adoptada, en el ciclo de desarrollo principal, es donde se agregan nuevas
funcionalidades, arreglos, cambios importantes a la aplicacin, prototipado y testing. Es ms frecuente
que se necesita fotos en esa etapa viva del desarrollo de la aplicacin.
En la rama del Release1, los cambios son menores, ms bien arreglos circunstanciales que no agregan
funcionalidad. En este caso, es menos frecuente la necesidad de crear Frozen Versions, pero puede ser
igualmente necesario.
406
Manejo de Versiones
NtesequelasFrozen Versions msnuevas,semuestranms
arribaenelrboldeversiones
407
Manejo de Versiones
LuegodeciertosarreglosenProduccin,nosinteresagenerarla
aplicacin.ParaesomarcamoslaDVRelease 1comoactiva.
GeneXus genera automticamente los programas y las estructuras de la BD, partiendo de la versin que
est activa.
Se puede marcar como activa una versin en desarrollo o una versin congelada. En ste ltimo caso,
no podremos hacer ninguna modificacin a la misma, solamente utilizarla para generar la aplicacin o
para realizar un impacto a la base de datos, o para comparar versiones.
Solamente puede haber una versin activa a la vez.
408
Manejo de Versiones
LaDevelopment Version queest activa,ser laqueseutilizar
paragenerarlaaplicacinalhacerunBuild (F5)
GeneXus nos indica
cul es la rama
activa
409
" #
$
! !
%&
"
'
" #
, %-. /
,)
'
!" #
!
#
!
/
&
%&
"
,
2
'
,3
/
)
#
# 01)
!
4 #
2
, $ !! . " #
,0
5 !" #
, 6/ 7 8 '9
,"
%&
"
$ !!
/
" #
#
"
!
!
"
#
#
!
"
$ !!
/
" #
#
#
0
"
!" #
#
!
4
! ;
!
1
!
$% & ' (
6/ 7 8 '9
!
4 !
)
#
!!
"
8 #!
!
10
10
255
25
905
145
550
210
150
300
890
230
2510
1340
320
1090
2510
1100
Como columna
Como pgina
Anlogo a un corte
de control que corta
primero por
CountryName, luego
por CustomerName
y luego por
InvoiceDate, y para
los registros de este
ltimo grupo,
sumariza
InvoiceAmount.
" #
!
Manipulable:
Prototipacin
Qu puede
especificarse dentro
del nodo Attributes?
Atributos
Funciones de agregacin
Expresiones
Lectura opcional
! "#
"
$
Lectura opcional
"
"
% Average(Count(InvoiceId)
Lectura opcional
Lectura opcional
Lectura opcional
Lectura opcional
Lectura opcional
Lectura opcional
&
'
&
#
!
Lectura opcional
Lista de valores
constantes
Operador Like
Lectura opcional
( )
& +,
'
Lectura opcional
!
Ejemplo: Se resuelve con 2 consultas select de las que luego se hace full join:
Lectura opcional
! "#
#$
$!
& '
& '
. +
& '
-/ +
& '
. +
& '
Curso 2013
Forma de entrega
El trabajo debe realizarse en forma individual y la entrega consiste en un archivo xpz de
nombre <Cedula>_<NombreApellido>.xpz con la resolucin de los ejercicios.
El xpz debe enviarse a la casilla ernestolopezmoreira@gmail.com antes del da 30 de Abril
(inclusive).
Curso 2011
Pgina 1
Curso 2011
direccin hidrulica, si tiene aire acondicionado y capacidad. Para esto utilizar una Free
Style grid. Junto a cada modelo debe aparecer la opcin de rentar.
Al seleccionar la opcin se redirige a una pantalla en la cual se muestran otra vez los
datos del modelo seleccionado y se pide al usuario que ingrese la fecha desde la cual
quiere alquilar y la cantidad de das. A travs de un botn se muestra una grilla con los
vehculos disponibles del modelo seleccionado y el costo total de la renta. El usuario
elige un vehculo y se emite un listado pdf que funciona como comprobante en el que
se muestra los datos del cliente, la fecha de la reserva, la cantidad de das, el total a
pagar y los datos del vehculo.
Al momento de confirmar se ingresa la reserva del vehculo. Una reserva est
identificada por el vehculo, y la fecha de la reserva (no es posible reservar un vehculo
ms de una vez en un da). La reserva tiene adems la cantidad de das que se alquil,
el kilometraje que se hizo durante el alquiler, el cliente que hizo la reserva y el estado
(abierta, cerrada). Al ingresar la reserva, esta queda abierta
Luego, cuando el cliente retorna con el vehculo un usuario administrador ingresa los
kilmetros realizados y marca la reserva como cerrada.
Objetivo:
Implementar la seguridad requerida para los clientes. Esto incluye mostrar solo las
opciones de men que corresponden.
Implementar para el cliente las funcionalidades de:
- Buscar Modelo
- Rentar auto
- Ver las reservas realizadas.
Implementar para el administrador las funcionalidades de:
- Reporte de estado de vehculos (permitir filtros por modelo)
- Ver reservas pendientes
- Reporte de historial de reservas de un vehculo.
- Reporte de reservas por rango de fechas. Agrupar por fecha los totales de
las reservas de cada modelo (solo los modelos que efectivamente tuvieron
reservas en el rango de fecha)
Consideraciones:
1) Instalar el User control MultiLevelMenu que viene en el archivo
MultiLevelMenu.zip:
http://wiki.gxtechnical.com/commwiki/servlet/hwiki?Default+Installation+Instructions
+for+User+Controls,
Pgina 2
Curso 2011
3) Para el manejo de la seguridad utilizar el tipo de dato WebSession. Este tipo de dato
permite almacenar pares {etiqueta, valor} a lo largo de la sesin del usuario. Por
ejemplo para la seguridad se puede utilizar la etiqueta userid para mantener el id del
usuario, entonces al momento de hacer el login guardamos este valor utilizando el
mtodo set del tipo de dato webSession:
&Session.set(userid, <NombreDeUsuario>)
Luego en el evento Start de la masterPage verificamos que este valor exista de lo
contrario redirigimos al usuario a, por ejemplo, la pantalla de login:
&Usuario = &Session.get(userid)
If
&usuario.isEmpty()
Login.call()
http://wiki.gxtechnical.com/commwiki/servlet/hwiki?WebSession,
Inscripcin:
El laboratorio se realizar en grupos de hasta 3 personas. Enviar correo a
ernestolopezmoreira@gmail.com con los nombres de los integrantes antes del 30 de
octubre.
Pgina 3
Curso 2011
Referencias:
Search de GeneXus: http://www.gxtechnical.com/gxsearch
Wiki de GeneXus: http://www.gxtechnical.com/wiki/
Grupo google del curso: http://groups.google.com.uy/group/desarrollo-deaplicaciones-con-genexus-tecnologo/
Pgina 4
Ejercicio 1
Se desea modelar un sistema para la administracin de las salas de la emergencia de un hospital. Al
ingresar un paciente a la emergencia se lo registra en el sistema. Cada paciente es identificado por el
nmero de paciente el cual es asignado en forma automtica por el sistema. Tambin se ingresan los
dos nombres y los dos apellidos (debiendo ingresar en forma obligatoria primer nombre y primer
apellido), cdula de identidad (nica para cada paciente) y fecha de nacimiento. El sistema registra la
fecha en la que se ingres al paciente y la fecha en que utiliz por ltima vez a la emergencia.
Lugo el paciente describe los sntomas que presenta y el usuario del sistema ingresa la descripcin en los
datos del paciente. nicamente se podr ingresar una descripcin por da para cada cliente. De esta
forma al momento de consultar los datos del paciente se vern las distintas visitas a la emergencia.
Finalmente hay que asignar al paciente una cama del hospital. Cada cama ser parte de una sala. Las
salas estn identificadas por una letra, se conoce la ubicacin dentro del Hospital (SUR, NORTE, ESTE,
OESTE), la cantidad total de camas, la cantidad de camas libres, fecha del ltimo mantenimiento. Luego
se ven las camas, cada una identificada por un nmero nico dentro de la sala. Se registra tambin la
fecha en la que fue ingresada en la sala, el estado, que puede ser OCUPADA o LIBRE. En caso de estar
ocupada se conoce tambin el paciente (y la descripcin de los sntomas) asignado a la cama.
Entonces, al ingresar un paciente, se toman los datos personales y de los sntomas presentados, se pasa
a la pantalla de mantenimiento de Salas y camas y se asigna una cama al paciente para que sea tratado
por los sntomas descriptos en el ingreso.
Forma de entrega
El trabajo debe realizarse en forma individual y la entrega consiste en un archivo xpz de nombre
<Cedula>_<NombreApellido>.xpz con la resolucin del ejercicio 1.
El xpz debe enviarse a la casilla ernestolopezmoreira@gmail.com antes del da 15 de setiembre
(inclusive).
a)
c)
Marca
{
MarcaId*
MarcaDescripcion
Auto
{
AutoId*
AutoDescripcion
}
}
Auto
{
AutoId *
AutoDescripcion
}
b)
Auto
{
AutoId *
AutoDescripcion
MarcaId
MarcaDescripcion
}
Marca
{
MarcaId *
MarcaDescripcion
AutoId
AutoDescripcion
}
Marca
{
MarcaId *
MarcaDescripcion
}
a)
c)
Auto
{
AutoId *
AutoDescripcion
PiezaTipoId
PiezaTipoDesc
}
PiezaTipo
{
PiezaTipoId *
PiezaTipoDesc
}
Auto
{
AutoId *
AutoDescripcion
}
PiezaTipo
{
PiezaTipoId *
AutoId*
PiezaTipoDesc
}
b)
Auto
{
AutoId*
AutoDescripcion
PiezaTipo
{
PiezaTipoId*
PiezaTipoDesc
}
}
PiezaTipo
{
PiezaTipoId *
PiezaTipoDesc
}
a)
c)
Pieza
{
PiezaId *
PiezaNombre
}
Auto
{
AutoId*
AutoDescripcion
Pieza
{
PiezaId*
PiezaNombre
}
}
b)
d)
Auto
{
AutoId*
AutoDescripcion
Pieza
{
PiezaId*
PiezaNombre
}
}
Pieza
{
PiezaId *
PiezaNombre
}
Pieza
{
PiezaId *
PiezaNombre
Auto
{
AutoId *
AutoDescripcion
}
}
Auto
{
AutoId *
AutoDescripcion
}
Automotora
{
AutomotoraId*
AutomotoraNom
}
a)
Automotora
AutomotoraId *
AutomotoraNom
Auto
AutoId *
AutoDescripcion
AutoPrecio
Envio
{
EnvioId*
EnvioFecha
AutomotoraId
AutomotoraNom
Fx EnvioTotal
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
}
Envio
EnvioId *
EnvioFecha
EnvioTotal
Sum(AutoPrecio)
EnvioAuto
EnvioId *
AutoId *
AutoDescripcion
AutoPrecio
b)
Automotora
AutomotoraId *
AutomotoraNom
Auto
AutoId *
AutoDescripcion
AutoPrecio
Envio
EnvioId *
EnvioFecha
AutomotoraId
c)
Automotora
AutomotoraId *
AutomotoraNom
Auto
AutoId *
AutoDescripcion
AutoPrecio
Envio
EnvioId *
EnvioFecha
AutomotoraId
AutomotoraNom
EnvioAuto
EnvioId *
AutoId *
EnvioAuto
EnvioId *
AutoId *
Automotora
{
AutomotoraId*
AutomotoraNom
}
Envio
{
EnvioId*
EnvioFecha
AutomotoraId
AutomotoraNom
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
}
a)
b)
c)
d)
Envo
Automotora
EnvioAuto
Auto
a)
b)
c)
d)
a)
Auto
{
AutoId*
AutoDescripcion
ContructorPaisId
ContructorPaisNombre
RepuestoPaisId
RepuestoPaisNombre
}
Pais
{
PaisId*
PaisNombre
}
b)
Auto
{
AutoId*
AutoDescripcion
ContructorPaisId
ContructorPaisNombre
RepuestoPaisId
RepuestoPaisNombre
}
Auto
{
AutoId*
AutoDescripcion
PaisId
PaisNombre
RepuestoPaisId
RepuestoPaisNombre
}
Pais
{
PaisId*
PaisNombre
}
c)
d)
Pais
{
PaisId*
PaisNombre
}
Pais
{
PaisId *
PaisNombre
}
10) 5 pts. Se tiene una aplicacin GeneXus para una ensambladora de Automviles.
La misma cuenta con la transaccin Envo para registrar los envos despachados a las automotoras. Se quiere
que al trabajar con cada lnea del detalle del envo (EnvioAuto), ya sea alta, baja o modificacin, se ejecute el
procedimiento logEnvio que recibe como parmetro el identificador del envo.
Envio
{
EnvioId*
EnvioFecha
EnvioHora
AutomotoraId
AutomotoraNom
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
}
a) logEnvio.call(EnvioId) ;
b) logEnvio.call(EnvioId) on AfterComplete;
c) logEnvio.call(EnvioId) on AfterValidate;
.
d) logEnvio.call(EnvioId) on AfterValidate level AutoId;
11) 7 pts. Se tiene una aplicacin GeneXus para una ensambladora de Automviles.
La misma cuenta con la transaccin Envo para registrar los envos despachados a las automotoras. Se necesita
emitir un listado de los envos por automotora. Se listaran solo aquellas automotoras para lasque hayan envos.
Determine cual es la implementacin correcta.
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
Automotora
{
AutomotoraId*
AutomotoraNom
}
c)
Envio
{
EnvioId*
EnvioFecha
AutomotoraId
AutomotoraNom
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
}
For each
Print --- (AutomotoraId, AutomotoraNom)
For each AutomotoraId
Print --- (EnvioId, EnvioFecha)
Endfor
Endfor
a)
For each
Print --- (AutomotoraId, AutomotoraNom)
For each
Print --- (EnvioId, EnvioFecha)
Endfor
Endfor
b)
d)
12) 7 pts. Se tiene una aplicacin GeneXus para una ensambladora de Automviles.
La misma cuenta con la transaccin Envo para registrar los envos despachados a las automotoras. Dado el
siguiente diseo de transacciones determine las tablas bases de los for each que aparecen a continuacin.
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
Automotora
{
AutomotoraId*
AutomotoraNom
}
a)
b)
c)
d)
Envio
{
EnvioId*
EnvioFecha
AutomotoraId
AutomotoraNom
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
}
For each
Print --- (EnvioId, EnvioFecha)
For each
Print --- (AutoId, AutoDescripcion)
Endfor
Endfor
13) 5 pts. Se tiene una aplicacin GeneXus para una ensambladora de Automviles.
La misma cuenta con la transaccin Envo para registrar los envos despachados a las automotoras. Dado el
siguiente diseo de transacciones determine qu tipo de for each es el siguiente:
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
Envio
{
EnvioId*
EnvioFecha
AutomotoraId
AutomotoraNom
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
}
Automotora
{
AutomotoraId*
AutomotoraNom
}
For each
Print --- (EnvioId, EnvioFecha)
For each
Print --- (AutomotoraId, AutomotoraNom)
Endfor
Endfor
a)
b)
c)
d)
JOIN
Producto cartesiano
Corte de control
Ninguna de las anteriores
14) 3 pts. Determine cul de las siguientes afirmaciones sobre Data Providers es correcta.
a) El Data Provider es un objeto que me permite procesar datos para obtener informacin en forma
estructurada (SDTs, bussines component, ext.).
b) El Data Provider es un objeto utilizado para actualizar la base de datos.
c) Ninguna de las anteriores es correcta.
15) 3 pts. Determine cul de las siguientes afirmaciones sobre Business component (BC) es correcta
a) Un objeto BC permite invocar una transaccin desde cdigo GeneXus como si esta estuviese
siendo ejecutada desde su Web Form.
b) A travs de un BC se puede actualizar la base de datos desde un Web Panel
c) Al llamar un BC, este no hace COMMIT sobre la base de datos y queda a cargo del programador
la confirmacin de los datos en la base de datos.
d) Todas las anteriores son correctas.
16) 6 pts. Se tiene un Web Panel SIN TABLA BASE con una grilla para listar todos los Autos que existen en el sistema.
Si se sabe que en la tabla autos existen 50 autos ingresados. Cuntas veces se ejecuta el evento load de la
grilla?
a)
b)
c)
d)
1 vez
50 veces
Ninguna vez
10 Veces
17) 8 pts. Se tiene una aplicacin GeneXus para una ensambladora de Automviles. La misma cuenta con la
transaccin Envo para registrar los envos despachados a las automotoras. La transaccin Automotora, que se
utiliza para mantener las automotoras a las cuales la ensambladora realiza los envos, tiene el atributo
AutomotoraEsPref para identificar aquellas que son clientes preferenciales de la ensambladora. Se quiere
construir un Web Panel que liste todos los envos del sistema mostrando en una columna el texto
PREFERENCIAL para aquellos envos a automotoras que son clientes preferenciales y el texto CLIENTE COMUN
para aquellas que no. Determine la opcin de implementacin que considere correcta.
Automotora
{
AutomotoraId *
AutomotoraNom
AutomotoraEsPref
}
a)
b)
c)
Envio
{
EnvioId*
EnvioFecha
AutomotoraId
AutomotoraNom
AutomotoraEsPref
}
a)
Auto
{
AutoId*
AutoDescripcion
ContructorPaisId
ContructorPaisNombre
RepuestoPaisId
RepuestoPaisNombre
}
Pais
{
PaisId*
PaisNombre
}
b)
Auto
{
AutoId*
AutoDescripcion
PaisId
PaisNombre
RepuestoPaisId
RepuestoPaisNombre
}
Pais
{
PaisId*
PaisNombre
}
c)
Auto
{
AutoId*
AutoDescripcion
ContructorPaisId
ContructorPaisNombre
RepuestoPaisId
RepuestoPaisNombre
}
Pais
{
PaisId*
PaisNombre
}
d)
Pais
{
PaisId *
PaisNombre
}
a) logEnvio.call(EnvioId) ;
b) logEnvio.call(EnvioId) on AfterValidate;
c) logEnvio.call(EnvioId) on AfterComplete;
d) logEnvio.call(EnvioId) on AfterValidate level AutoId;
Automotora
{
AutomotoraId*
AutomotoraNom
}
c)
Envio
{
EnvioId*
EnvioFecha
AutomotoraId
AutomotoraNom
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
}
a)
b)
d)
For each
Print --- (AutomotoraId, AutomotoraNom)
For each
Print --- (EnvioId, EnvioFecha)
Endfor
Endfor
For each
Print --- (AutomotoraId, AutomotoraNom)
For each AutomotoraId
Print --- (EnvioId, EnvioFecha)
Endfor
Endfor
Automotora
{
AutomotoraId*
AutomotoraNom
}
a)
b)
c)
d)
Envio
{
EnvioId*
EnvioFecha
AutomotoraId
AutomotoraNom
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
}
For each
Print --- (EnvioId, EnvioFecha)
For each
Print --- (AutoId, AutoDescripcion)
Endfor
Endfor
Envio
{
EnvioId*
EnvioFecha
AutomotoraId
AutomotoraNom
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
}
Automotora
{
AutomotoraId*
AutomotoraNom
}
For each
Print --- (EnvioId, EnvioFecha)
For each
Print --- (AutomotoraId, AutomotoraNom)
Endfor
Endfor
a)
b)
c)
d)
Producto cartesiano
Corte de control
JOIN
Ninguna de las anteriores
8) 3 pts. Determine cul de las siguientes afirmaciones sobre Data Providers es correcta.
a) El Data Provider es un objeto que me permite procesar datos para obtener informacin en forma
estructurada (SDTs, bussines component, ext.).
b) El Data Provider es un objeto utilizado para actualizar la base de datos.
c) Ninguna de las anteriores es correcta.
9) 3 pts. Determine cul de las siguientes afirmaciones sobre Business component (BC) es correcta
a) Un objeto BC permite invocar una transaccin desde cdigo GeneXus como si esta estuviese
siendo ejecutada desde su Web Form.
b) A travs de un BC se puede actualizar la base de datos desde un Web Panel
c) Al llamar un BC, este no hace COMMIT sobre la base de datos y queda a cargo del programador
la confirmacin de los datos en la base de datos.
d) Todas las anteriores son correctas.
10) 6 pts. Se tiene un Web Panel SIN TABLA BASE con una grilla para listar todos los Autos que existen en el sistema.
Si se sabe que en la tabla autos existen 50 autos ingresados. Cuntas veces se ejecuta el evento load de la
grilla?
a)
b)
c)
d)
1 vez
10 Veces
50 veces
Ninguna vez
11) 8 pts. Se tiene una aplicacin GeneXus para una ensambladora de Automviles. La misma cuenta con la
transaccin Envo para registrar los envos despachados a las automotoras. La transaccin Automotora, que se
utiliza para mantener las automotoras a las cuales la ensambladora realiza los envos, tiene el atributo
AutomotoraEsPref para identificar aquellas que son clientes preferenciales de la ensambladora. Se quiere
construir un Web Panel que liste todos los envos del sistema mostrando en una columna el texto
PREFERENCIAL para aquellos envos a automotoras que son clientes preferenciales y el texto CLIENTE COMUN
para aquellas que no. Determine la opcin de implementacin que considere correcta.
Automotora
{
AutomotoraId *
AutomotoraNom
AutomotoraEsPref
}
a)
b)
c)
Envio
{
EnvioId*
EnvioFecha
AutomotoraId
AutomotoraNom
AutomotoraEsPref
}
12) 10 pts. Se tiene una aplicacin GeneXus para una ensambladora de Automviles
Se ensamblan distintas marcas de autos (marca). Un Auto tiene una Marca. A su vez pueden haber muchos
autos de una marca
Determine el diseo de transacciones que considere correcto para representar dicha realidad.
a)
c)
Marca
{
MarcaId*
MarcaDescripcion
Auto
{
AutoId*
AutoDescripcion
}
}
Auto
{
AutoId *
AutoDescripcion
MarcaId
MarcaDescripcion
}
b)
Auto
{
AutoId *
AutoDescripcion
}
Marca
{
MarcaId *
MarcaDescripcion
}
Marca
{
MarcaId *
MarcaDescripcion
AutoId
AutoDescripcion
}
13) 10 pts. Se tiene una aplicacin GeneXus para una ensambladora de Automviles
Un Auto est compuesto por varios tipos de Piezas (PiezaTipo). Un tipo de pieza puede ser parte de muchos
autos.
Determine el diseo de transacciones que considere correcto para representar dicha realidad.
a)
c)
Auto
{
AutoId *
AutoDescripcion
}
PiezaTipo
{
PiezaTipoId *
AutoId*
PiezaTipoDesc
}
Auto
{
AutoId *
AutoDescripcion
PiezaTipoId
PiezaTipoDesc
}
PiezaTipo
{
PiezaTipoId *
PiezaTipoDesc
}
b)
Auto
{
AutoId*
AutoDescripcion
PiezaTipo
{
PiezaTipoId*
PiezaTipoDesc
}
}
PiezaTipo
{
PiezaTipoId *
PiezaTipoDesc
}
14) 10 pts. Se tiene una aplicacin GeneXus para una ensambladora de Automviles
Un Auto est compuesto por varias Piezas (Pieza). Ests piezas son utilizadas nicamente para esos Autos por lo
que no puede haber una Pieza que no est asociada a un Auto.
Determine el diseo de transacciones que considere correcto para representar dicha realidad.
Auto
{
AutoId *
AutoDescripcion
PiezaId
PiezaNombre
}
a)
c)
Pieza
{
PiezaId *
PiezaNombre
}
Auto
{
AutoId*
AutoDescripcion
Pieza
{
PiezaId*
PiezaNombre
}
}
Pieza
{
PiezaId *
PiezaNombre
}
b)
Pieza
{
PiezaId *
PiezaNombre
Auto
{
AutoId *
AutoDescripcion
}
}
d)
Auto
{
AutoId *
AutoDescripcion
}
Auto
{
AutoId*
AutoDescripcion
Pieza
{
PiezaId*
PiezaNombre
}
}
15) 5 pts. Se tiene una aplicacin GeneXus para una ensambladora de Automviles.
A partir del siguiente diseo de transacciones, determine la estructura fsica de las tablas que GeneXus crear.
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
Automotora
{
AutomotoraId*
AutomotoraNom
}
a)
Automotora
AutomotoraId *
AutomotoraNom
Auto
AutoId *
AutoDescripcion
AutoPrecio
Envio
{
EnvioId*
EnvioFecha
AutomotoraId
AutomotoraNom
Fx EnvioTotal
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
}
Envio
EnvioId *
EnvioFecha
EnvioTotal
Sum(AutoPrecio)
EnvioAuto
EnvioId *
AutoId *
AutoDescripcion
AutoPrecio
b)
c)
Automotora
AutomotoraId *
AutomotoraNom
Auto
AutoId *
AutoDescripcion
AutoPrecio
Envio
EnvioId *
EnvioFecha
AutomotoraId
AutomotoraNom
Automotora
AutomotoraId *
AutomotoraNom
Auto
AutoId *
AutoDescripcion
AutoPrecio
Envio
EnvioId *
EnvioFecha
AutomotoraId
EnvioAuto
EnvioId *
AutoId *
EnvioAuto
EnvioId *
AutoId *
Automotora
{
AutomotoraId*
AutomotoraNom
}
Envio
{
EnvioId*
EnvioFecha
AutomotoraId
AutomotoraNom
Auto
{
AutoId *
AutoDescripcion
AutoPrecio
}
}
a)
b)
c)
d)
17) 5 pts. Se tiene una aplicacin GeneXus para una ensambladora de Automviles.
Dado el siguiente diagrama de Bachman, determine la tabla extendida de EnvioAuto.
Envo
Automotora
EnvioAuto
Auto
a)
b)
c)
d)