Tabla de Contenido
TABLA DE CONTENIDO ... 2
INTRODUCCIÓN ... 3
OBJETIVO ... 3
ETAPAS DEL PROYECTO ... 4
PUBLICANDO LA INFORMACIÓN. ... 5
TABLA : MODEL... 5
TABLA : OBJECT... 5
TABLA : TABLE... 6
TABLA: INDEX... 7
TABLA: IDXATT... 7
TABLA: ATTRIBUTE... 9
TABLA: FORMULA... 10
TABLA: TRNSTRUCTURE... 11
TABLA: TRNLVL... 12
TABLA: TBLATT... 12
TABLA: GROUP... 13
TABLA: GRPATT... 13
TABLA: DOMAIN... 13
TABLA: TBLSUBOR... 14
TABLA: TBLSUBBY... 14
TABLA: TBLEXTENDED... 14
TABLA: DVATT... 14
TABLA: CROSSREF... 15
PUBLICANDO SERVICIOS ... 15
¿QUÉ COSAS SE PUEDEN HACER? ... 17
TECNOLOGÍA UTILIZADA ... 17
¿QUÉ ES UN OLE DB PROVIDER? ... 17
PROGRAMANDO CON GXPUBLIC ... 18
CON GENEXUS... 18
CON VB (O VFP) VÍA ADO ... 20
Introducción
Muchas veces nos encontramos frente a la necesidad de obtener información de una Base de Conocimiento GeneXus (KB).
¿ Cómo realizamos esta tarea?
En GeneXus, la mejor forma de obtener un listado del cabezal de los objetos, por ejemplo es en la vista de Folder. Contiene el nombre, la descripción, el tipo y la fecha de
modificación del objeto.
Sin embargo, muchas veces se quiere alguna otra información, como ser la fecha de especificación, qué estilo tiene asociado el objeto, en que generador será generado, etc.
Toda esta información extra se puede ver, aunque no en forma tabular, desde el call browser.
Este mecanismo es útil en muchos casos, pero surgen problemas cuando se quiere obtener documentación con cierto formato de los datos contenidos en la KB, por ejemplo:
quiero una planilla Excel con todos los objetos pertenecientes al núcleo de mi aplicación.
Aún más complejo es realizar consultas como ser: ¿ cuál es la tabla que tiene más atributos? ¿Qué atributos no tienen dominio?, etc.
Nuestros clientes cada vez más nos piden alguna forma de acceder a los datos de una KB, para poder realizar sus propias consultas, documentos, etc.
Objetivo
El proyecto “GXpublic” tiene un objetivo bien claro que es la “exposición”, “publicación” de la información de una KB GeneXus.
El objetivo es claro si se explicita el significado de “publicar una KB GeneXus”
Una herramienta que permita publicar una KB debe cumplir:
!"Debe exponer toda la información necesaria para realizar consultas sobre una KB:
#" Modelos
#" Objetos (Datos, Propiedades, Eventos, Métodos, Reglas, Ayuda)
#" Atributos
#" Índices
#" Estructuras de Transacciones e Índices.
#" Fórmulas
#" Tablas
#" Referencias entre objetos, atributos.
#" Grupos, dominios.
#" Pantallas.
!"Permitir acceder a ciertos servicios sobre una KB (o elementos de una KB), con el objetivo de poder realizar el “full cycle”
#" Hacer el “Impact Database”.
#" Ejecutar la reorganización (hace el “update model”).
#" Mandar especificar y generar todos los programas.
#" Transferirlos y mandarlos a compilar.
!"La forma de acceder a los datos debe ser simple en los lenguajes VB, VFP y JAVA ya que esto abre las puertas para poder acceder a una KB desde el propio
GeneXus. Además de permitir que usuarios avanzados programen directamente en estos lenguajes.
Etapas del Proyecto
El proyecto “GXpublic” fue dividido en varias etapas:
!"Publicar la información básica de una KB GeneXus cumpliendo con el requerimiento de que debe haber una forma fácil de acceder a los datos.
La información que será publicada en la primera etapa será:
#" Modelos
#" Objetos
#" Tablas
#" Atributos
#" Índices
#" Composición de Índices
#" Estructura de transacciones
#" Niveles de transacciones
#" Atributos de tablas
#" Grupos
#" Composición de grupos
#" Fórmulas
#" Dominios
!"Publicar información avanzada
#" Referencias entre objetos.
#" Eventos, reglas, condiciones, propiedades.
#" Pantallas.
#" Tabla extendida.
#" Subordinaciones.
!"Agregar servicios sobre una KB
#" Permitir modificaciones sobre algunos elementos.
#" Generación de una sentencia SQL partiendo de un grupo de atributos.
#" “Full Cycle”
Publicando la información.
A continuación se mostrará cuál es la información a la cuál se va ha poder acceder en esta primera versión de “GXpublic”
La información esta publicada en forma tabular, por lo que resulta muy sencillo e intuitivo acceder a la misma. Más adelante veremos que GXpublic fue desarrollado para utilizar las facilidades de acceso de tecnologías existentes.
De ahora en más veremos una KB GeneXus como un DataSource, el cuál cuenta con un conjunto de tablas en las cuáles se almacena la información de la KB, sin pensar en el “COMO”
esta almacenada la información.
Veamos que tablas tiene un KBDataSource:
Tabla : Model
Información de los modelos de una KB.
MdlId * Identifica a un modelo dentro de la KB
Integer
MdlNam Nombre del Modelo String (largo 30) MdlPath Path del modelo String (largo 30) MdlReorgTS Fecha y hora de la última
especificación.
DATE
Tabla : Object
Información de los objetos de una KB.
MdlId*
ObjCls* Tipo de objeto. Integer
(enumerado) ObjId* Identificador del objeto. Integer
ObjNam Nombre del objeto String (largo 30)
ObjOwner Id del folder en donde se encuentra el objeto. Integer
ObjDsc Descripción del objeto String (largo 30)
ObjTyp Tipo del objeto (DW) Integer
(enumerado) ObjMainGen Id del Generador asociado si el objeto es
main (0 si no es main)
Integer
ObjCreTS Creación del objeto DATE
ObjUpdTS Fecha de modificación del objeto DATE ObjSpcTS Fecha de especificación del objeto (Null si no
tiene)
DATE
ObjSty Id del style asociado al objeto. (0 si no tiene) Integer ObjTblAssc Id de Tabla asociada (0 si no tiene o no
aplica)
Los valores posibles para ObjCls son:
!"transaction TRN = 0
!"procedure PRC = 1
!"report RPT = 2
!"menu MNU = 3
!"work panel WKP = 4
!"data view DV = 6
!"table TBL = 7
!"folder FLD = 8
!"prompt PMT = 12
!"web panel WBP = 13
!"external program XPG = 14
!"menu bar MBR = 17
!"transaction style STRN = 18
!"procedure style SPRC = 19
!"report style SRPT = 20
!"work panel style SWKP = 21
!"prompt style SPMT = 22
!"web panel style SWBP = 23
!"menu bar style SMBR = 24 Los valores posibles para ObjTyp son:
!"fact table DWH = 2
!"dimension DIM = 4
Los valores para todo identificador es un número entero mayor que cero.
Los campos ObjUpdTS, ObjCreTS y ObjSpcTS, son TimeStamps (de ahí viene el posfijo) , los mismos poseen hora y fecha. Estos campos en VB pueden ser asignados
directamente a un campo de tipo DATE de VB. En VFP este campo debe ser
almacenado en una variable de tipo datetime. Este valor puede ser pasado a un string utilizando la función ttoc de vfp.
La fecha nula es 1899-12-30 00:00:00.
El campo ObjTblAsoc se aplica únicamente cuando el objeto es un Data View.
Tabla : Table
Información de las tablas de una KB.
MdlId*
TblId* Identificador Integer
TblNam Nombre String
TblDsc Descripción String (largo 30)
Tabla: Index
Información de índices de una KB. Los indices de una KB pueden ser pertenecientes a una tabla o a un Data View.
MdlId*
ObjCls* Clase (puede ser tabla o DV ) ObjId*
IdxId* Identificador Integer
IdxNam Nombre String
IdxTyp Tipo Integer (enumerado)
IdxSrc Sistema | Usuario Integer (enumerado)
Los valores posibles para IdxTyp son:
!"Único GX_UNIQUE = 1
!"Duplicado GX_DUPLICATE = 2 Los valores posibles para IdxSrc son:
!"Automático GX_AUTO = 1
!"Usuario GX_USER = 2
Cuando el índice es perteneciente a un Data View este campo vale GX_USER.
Tabla: IdxAtt
Composición de índices
MdlId*
ObjCls*
ObjId*
IdxId*
AttId*
IdxOrder Orden Integer (enumerado)
Los valores posibles para IdxOrder son:
!"Ascending GX_ASC = 1
!"Descending GX_DESC = 0
¿ Cómo determinar la posición de los atributos en el índice?
Si se tiene un índice Idx1 = A, B y otro Idx2 = B,A el orden de los atributos son las posiciones en el índice, es decir en la tabla va a estar primero Idx1, A y luego Idx1, B para el Idx2 va a estar primero Idx2, B y luego Idx2, A.
Tabla: Attribute
Información sobre atributos de una KB MdlId*
AttId* Identificador Integer
AttNam Nombre String
AttDsc Descripción String (largo 30)
AttTyp Tipo de atributo Integer (enumerado) AttCls Clase de atributo Integer (enumerado)
AttLen Largo Integer
AttDec Decimales Integer
AttRng Rango String (largo 80)
AttSign Signo Integer
AttPic Picture String (largo 30)
AttDom Dominio al cual esta asociado (0 si no tiene)
Integer AttIdSup Id del supertipo (0 si no tiene) Integer
Los valores posibles para AttTyp son :
!"Integer GX_INT = 4
!"Character GX_CHAR = 5
!"Date GX_DATE = 6
!"LongVarChar GX_LONGVARCHAR = 8
!"DateTime GX_DATETIME = 12
!"VarChar GX_VARCHAR = 13 Los valores posibles para AttCls son :
!"Primario GX_PRI_CLASS = 1
!"Secondario GX_SEC_CLASS = 2
!"Inferido GX_INF_CLASS = 3
!"Formula Vertical GX_VERTICAL = 4
!"Formula Horizontal GX_HORIZONTAL = 5
Tabla: Formula
Información de fórmulas de una KB.
MdlId*
AttId*
FmlPos* Posición del token en la
fórmula
Integer
FmlTknTyp Tipo de token Integer (enumerado)
FmlTknVal Valor del token String (largo 30)
FmlTknObjCls Clase si el token es de tipo ATT o OBJ
Integer (enumerado) FmlTknObjId Id del objeto si el token es
de tipo ATT o OBJ
Integer
Las fórmulas son consideradas un conjunto de tokens. Cada uno de estos tokens tiene un tipo determinado, el cual es almacenado en FmlTknTyp y puede tomar los siguientes valores:
!"Abre paréntesis GXOB = 1
!"Call a función GXFN = 2
!"Nombre de atributo GXNA, = 3
!"Nombre de constante GXNC, = 4
!"Cierra paréntesis GXCB,= 5
!"Operador +, - GXPL,= 6
!"Operador *,/ GXPR, = 7
!"Comma separator GXCM, = 8
!"NOT GXNT = 9
!"AND OR GXAN,= 10
!"Relational oper. GXRE, = 11
!"Expression GXEXP, = 12
!"Sum GXSUM,= 13
!"Count GXCOU, = 14
!"Aerage GXAVE, = 15
!"Maximum GXMAX,= 16
!"Minimum GXMIN, = 17
!"IF ... GXIF, = 18
!"Punto y coma GXSC, = 19
!"Otherwise GXOT, = 20
!"Error GXERR_TOKEN = 21
!"EOExpression GXEN, = 22
!"Comment GXCO, = 23
!"User Variable (&) for rules/commands GXUV, = 24
!"User Variable Array '&xx(' GXUA, = 25
!"CoNtinuation Line GXCN, = 26
!"String to replace '&' with '&&' GXAM, = 27
!"CLass id used for calls GXOCL, = 28
!"Object Id used for calls GXOI, = 29
!"ConTrol ID/Name GXCT, = 30
!"Control Type Id GXCI, = 31
!" Control ID/Name GXFMT = 32
SUM(CliSubTot) es una fórmula compuesta por 3 tokens ‘SUM( ‘ de tipo literal,
‘CliSubTot’ de tipo ATT y ‘)’ literal.
Esto quiere decir que para el segundo token se guarda en FmlTknObjCls que es un ATT y en FmlTknObjId se guarda la identificación del atributo.
Para los tokens literales su valor se obtiene en el campo FmlTknVal.
Tabla: TrnStructure
Información de la estructura de una transacción
MdlId*
TrnId*
TrnLvlId* Identificador del nivel Integer
TrnItmTyp* Tipo de ítem Integer (enumerado)
TrnItmId* Identificador del ítem Integer
TrnItmIskey Si el ítem es un atributo indica si es key ( tiene *)
Integer
¿Como se guarda la información en esta tabla?
Supongamos que tenemos la siguiente Trn:
A*
B (C*
(D*
E) ) F (G*
H)
Para guardar la información en la tabla se considero que un nivel de una transacción es un conjunto de Items, donde cada ítem puede ser un nivel o un atributo. Por tanto el primer nivel de la trn lo podemos ver así :
A*
B (Level 2) F
(Level 4) El Level 2 así:
C*
(Level 3) El Level 3 así : D*
E
Entonces en la tabla tendremos:
MdlId , TrnId, 1, ATT, IdA MdlId, TrnId, 1, ATT, IdB MdlId, TrnId, 1, LVL, IdLvl2 MdlId, TrnId, 1, ATT, IdF MdlId, TrnId, 1, LVL, idLvl4 MdlId, TrnId, 2,ATT, idC MdlId, TrnId, 2, LVL, idLvl3
…..
Los valores que puede tomar TrnItmTyp son :
!"Level ITM_LEVEL = 0
!"Attribute ITM_ATT = 1
Tabla: TrnLvl
Niveles de una transacción y tablas asociadas a cada nivel MdlId*
TrnId*
TrnLvlIdSup* Identificador del nivel superior
Integer
TblId* Tabla asociada Integer
Tabla: TblAtt
Atributos de una tabla.
MdlId*
TblId*
AttId*
TblAttIsKey El atributo es llave en la tabla
TblAttRed Redundante Integer
TblAttStd Almacenado Integer
La posición de un atributo en una tabla puede ser determinada por el orden de aparición en la tabla. Es decir para la tabla con atributos (A,B) primero aparece el atributo A y luego el atributo B.
Tabla: Group
Grupos de una KB.
MdlId*
GrpId* Identificador Integer
GrpNam Nombre String
Tabla: GrpAtt
Composición de grupos
MdlId*
GrpId*
AttId*
Tabla: Domain
Dominios de una KB
MdlId*
DomId* Identificador Integer
DomNam Nombre String
DomDsc Descripción String (largo 30)
DomTyp Tipo Integer (enumerado)
DomLen Largo Integer
DomDec Decimales Integer
DomRng Rango String (largo 80)
DomSign Signo Integer
DomPic Picture String (largo 30)
El tipo DomTyp es del mismo tipo que el de AttTyp.
Tabla: TblSubor
Tablas directamente subordinadas a una tabla MdlId*
TblId*
TblSubPos*
TblSubId Identificador de tabla subordinada.
Numérico
Tabla: TblSubBy
Atributos de subordinación.
MdlId*
TblId*
TblSubPos* I
AttId1* Atributo de tabla
superordinada
AttId2* Atributo de tabla subordinada
Tabla: TblExtended
Tablas pertenecientes a la tabla extendida de una tabla.
MdlId*
TblId*
TblExPos* Numérico
TblExTblId Identificador de tabla perteneciente a la extendida de TblId
Numérico
Tabla: DVAtt
Composición de Data Views
MdlId*
DVId* Identificador del Data View Numérico
AttId* Id del atributo
correspondiente al Internal
Numérico
Name.
AttExtNam External Name String (largo 30)
Tabla: CrossRef
En esta tabla se exponen las referencias entre objetos, las consultas sobre esta tabla son válidas siempre que se instancie en la sentencia select
el objeto referenciado o el objeto que referencia.
Es decir serán válidas:
• Select * From CrossRef Where ObjCls = 0 and ObjId = 3
• Select * From CrossRef Where ItmRefCls = 1 and ObjId = 3
MdlId*
ObjCls* Clase del objeto que referencia
ObjId* Id del objeto que referencia
RefTyp* Tipo de referencia Numérico
ItmRefCls* Clase de objeto referenciado Numérico ItmRefId* Id de objeto referenciado Numérico
Los valores que puede tomar RefTyp son:
• RUL_TYP = 3 El objeto es referenciado en las rules
• EVT_TYP = 4 El objeto es referenciado en los eventos
• CND_TYP = 5 El objeto es referenciado en las conditions
• SCR_TYP = 6 El objeto es referenciado en la pantalla o en un printblock.
• HLP_TYP = 7 El objeto es referenciado en el help
• DOC_TYP = 8 El objeto es referenciado en la documentación
• DOM_TYP = 10 El objeto es referenciado en un dominio (por ej.
Atributos)
• COMP_TYP = 30 El objeto es referenciado en una estructura. (por ej. Un atributo es referenciado en la estructura de una transacción)
• LAY_TYP = 11 El objeto es referenciado en el código de un proc.
Publicando Servicios
El GXpublic como se dijo anteriormente contará con un conjunto de servicios sobre una Base de Conocimiento. Hoy se tienen ya implementados algunos servicios:
!"GetRelatedAttributes(NumMod as Integer, Atributos as Collection, AtributosRelacionados as Collection)
#" Objetivo:
Dado un modelo y un conjunto de atributos del mismo obtiene el conjunto de atributos relacionados. (A partir de los atributos se
calcula su tabla base y luego se incluyen todos los atributos pertenecientes a las tablas extendidas de las subordinadas a esa tabla)
#" Parámetros:
• NumMod [Entrada] Número del modelo al cuál pertenecen los Atributos
• Atributos [Entrada] Conjunto de atributos ingresados como una colección de enteros.
• AtributosRelacionados [Salida] Atributos relacionados a Atributos
!"String GetSqlStatement(NumMod as Integer, Atributos as Collection , sentWhere as String, attsOrder as Collection)
#" Objetivo:
Construir una sentencia SELECT que involucre los atributos pertenecientes a Atributos, con la condición expresada en sentWhere y cuyo ORDER está dado por el conjunto de atributos dado en attsOrder.
#" Parámetros:
• NumMod [Entrada] Número del modelo al cuál pertenecen los Atributos
• Atributos [Entrada] Conjunto de atributos ingresados como una colección de enteros
• SentWhere [Entrada] Condiciones de filtro
• AttsOrder [Entrada] Atributos para el ORDER
#" Salida:
• Sentencia SELECT generada.
Para acceder a estos servicios en la versión 1.0, los programadores deben poner una referencia a una dll llamada “dynq 1.0 Library”, la cuál expone un objeto llamado GXDynQuery, sobre el cuál se implementan los dos métodos anteriores además de un método extra para poder setear el Path de la KB a la cuál se va a acceder.
Ejemplo : Armado de una sentencia SELECT Dim dinq As GxDynQuery
Dim Atts As New Collection Dim Order As New Collection Dim whereStr As String
Atts.Add(1) AttsAdd(5) Order.Add(5)
WhereStr = “CliCuenta > 100”
Set dinq = New GxDynQuery
dinq.SetKBase "c:\evento\kb"
Dim mdl As Integer mdl = mdlid
sqlStm = dinq.GetSqlStatement(mdl, Atts, whereStr, Order)
¿Qué cosas se pueden hacer?
!"Documentación Personalizada
Se pueden crear herramientas que accedan a una KB y extraigan información valiosa de modelos, objetos, atributos y con ella crear una documentación de la KB en cierto formato deseado (ej. Planillas excel, documentos word, etc)
!"Manejo de Versiones de KBs.
!"Consultas particulares para extraer ciertas características de una KB:
#" Atributos sin dominio.
#" Estructura de transacciones.
#" Listados de objetos modificados luego de una fecha dada.
#" Datos de objetos.
#" Obtener la estructura de folders, por ej: para mostrarla en un treeView.
#" Atributos fórmulas
#" Chequeo de posibles problemas, por ej. Ver si subtipo y supertipo están en una misma trn.
#"
!"Tablas Subordinadas. Se pueden llegar a realizar diagramas de tablas.
!"Poder realizar el FullCycle (no actualmente)
Seguir enumerando cosas es un poco redundante teniendo la estructura de tablas, para saber si cierta consulta se puede satisfacer solo basta mirar si la información se encuentra en alguna tabla.
Tecnología utilizada
El GXpublic es una Dynamic Link Library (DLL) que contiene un OLE DB Provider, el cuál es el encargado de exponer los datos en forma tabular, y es el que permite trabajar con una KB como si fuera un DataSource con sus tablas asociadas.
¿Qué es un OLE DB Provider?
OLEDB es una tecnología que se encuentra dentro de una estrategia llamada Universal Data Access (UDA), cuyo objetivo primordial es la estandarización del acceso a cualquier tipo de datos.
OLEDB es un conjunto de interfaces COM que proveen a las aplicaciones el acceso uniforme a datos almacenados en diferentes formas, además de permitir la
implementación de servicios adicionales.
Dentro de OLEDB encontramos dos componentes fundamentales los Providers y los Consumers (Proveedores y consumidores de datos)
La idea es que los proveedores de datos escondan la lógica de acceso a los datos y expongan datos en forma tabular, sin importar cuál es su origen, además puede exponer servicios sobre estos datos.
La gran ventaja de realizar esto es es que los consumidores acceden a los datos a través de interfaces conocidas, sin importarle como y dónde están almacenados los datos.
Hoy en día existen interfaces de acceso estándares (ADO-ActiveX Data Objects), las cuáles permiten el acceso a proveedores realizados con OLEDB.
ADO es la interface de más alto nivel para acceder a cualquier tipo de datos expuesto por un OLEDB Provider, por tanto es la forma con la cual se puede acceder a GXpublic desde lenguajes como VB,VFP y JAVA.
Más información de ADO: http://www.microsoft.com/data/ado/default.htm
En VC++ se puede acceder a los providers utilizando ADO, o interfaces de más bajo nivel.
Por más información sobre OLEDB y UDA http://www.microsoft.com/data/
Importante: Para poder utilizar todas las funcionalidades brindadas por GXpublic deben estar instalados los Microsoft Data Access Components (MDAC) versión 2.1.
Estos componentes son instalados por el Service pack 3 del Visual Studio 6.0 o se pueden obtener en http://www.microsoft.com/data/download2.htm
Programando con GXpublic
Con GeneXus
A partir de la versión 6 Evolution II de GeneXus, existe la posibilidad de acceder a las tablas del GxPublic vía DataView (solo para Visual Basic). Para ello a partir de dicha versión existe un nuevo formato para los Data Views, llamado ADO.
Para utilizarlo hay que agregar en “Platform Specific Information” la plataforma Access y cambiar las siguientes propiedades.
Tabla Name: Nombre de la tabla del GxPublic (Ej: Model)
Database Location: Path de la KB GeneXus, para hacerlo dinámico ver Data View Dinámicos.
Data Format: ADO ADO Information
Provider: Id del provider, en el caso del GXPublic es : “GXPublic.GXPublic.1” (sin las comillas”
Por el momento solo funciona en procedimientos (que no graben), reportes y Work Panels ya que GXpublic no permite hacer modificaciones a la KB.
También existe la posibilidad de acceder vía la llamada a programas externos.
#" GXOpenKB(pathKB, successfuly) Abre una KB
o PathKB : [in] Path de la KB
o Successfuly: [out] 1-abrió 0-no abrió
#" GXOpenTable(NameTable,val1,val2,val3)
Abre una tabla instanciando los valores de la clave con val1,val2 y val3.
o NameTable: [in] nombre de la tabla a abrir o Vali: [in] valor para el i-ésimo valor de la clave
#" GXLoadCurrent(Vals(), count)
Recupera los valores del registro actual.
o Vals() ; [out] Devuelve un array con los valores del registro actual de la tabla y KB abierta.
o Count : [out] Devuelve el tamaño del array.
#" GXMoveNext()
Se mueve al próximo registro si es posible.
#" GXEOTable()
Indica si se ha llegado al final de la tabla
Por ejemplo un evento GeneXus que cargue los Modelos podría ser:
Event ‘Load’
// Abre kb
call('gxOpenKb', &KBNAME) // Apertura de tabla de modelos
&msg = 'Model'
call('gxOpenTable',&msg)
// Recorrida de los modelos de la KB
&endofTable = udp('gxeotable') do while &endofTable = 0
call('gxLoadCurrent',&vals(),&cantCol) &MdlId = &vals(1)
&MdlName = &vals(2) &MdlPath = &vals(3) call('gxMoveNext')
&endofTable = udp('gxeotable') Load
Enddo EndEvent
Nota: Las funciones anteriormente descriptas no fueron implementadas como programas estándar, son solo una guía para mostrar un ejemplo con GeneXus.
Si se quiere usar esta idea cada programador debe implementar las funciones él mismo y utilizarlas como programas externos.
Con VB (o VFP) vía ADO
Otra forma de acceder es vía ADO, esta opción es para programadores avanzados.
En ADO existen un conjunto de componentes mediante los cuáles podemos acceder a un Provider.
Los componentes que utilizaremos son:
!"Connection
o Representa una conexión a un Data Source.
o Los métodos utilizados son:
#" Open(ConnectionString)
#" Close
!"RecordSet
o Representa un conjunto de registro de una tabla base.
o Los métodos utilizados son:
#" Open(StringCommand)
• Carga el Recordset con el conjunto de registros especificado en StringCommand
#" MoveFirst
• Se va al primer registro del RecordSet
#" MoveLast
• Se va al último registro del RecordSet
#" EOF
• Indica si se llegó al final del RecordSet (no hay más registros)
#" Fields(i) en VB o Fields(i).value en VFP
• Devuelve el valor de la I-ésima columna del registro actual del RecordSet.
Los valores de las columnas pueden ser recuperados también usando Fields(<nameColumn>), por ej.
Record.Fields(“MdlNam”)
#" Close
Un ejemplo de una función VB que despliega los nombres de los modelos de una KB sería:
Dim myConn As ADODB.Connection Dim myTable As ADODB.Recordset
' Apertura de una KB
myConn.Open ("Provider=GXPublic.GXPublic.1;Data Source=C:\MisModelos\ModeloPrueba")
' Carga de los modelos de una KB a un RecordSet
' Se indica a quien pertenece este recordset myTable.ActiveConnection = myConn myTable.Open ("SELECT * FROM MODEL")
' Se recorren los modelos y se despliegan sus nombres If Not myTable.EOF Then
myTable.MoveFirst
Do While Not myTable.EOF
MsgBox (myTable.Fields("MdlNam")) myTable.MoveNext
Loop
myTable.Close myConn.Close End If
El Open de los recordset recibe como parámetro un comando que indica que registros se deben cargar al recordset, este comando es una sentencia SQL.
La sintaxis para la construcción de las sentencias se explica en forma detallada en la siguiente sección.
Ejemplos:
Quiero todos los objetos del modelo 1 $ CommandString = “SELECT * FROM MODEL WHERE MDLID = 1”
Quiero todas las transacciones $ CommandString = “Select * From OBJECT where MdlId
= 1 and ObjCls = 0”
En la sentencia hoy por hoy existen algunas restricciones:
!"Aunque se pongan atributos en el SELECT se considera siempre *. Por ej:
SELECT MdlId, MdlNam es equivalente a SELECT *
!"El ORDER es ignorado, siempre se ordena por clave primaria.
!"Las consultas se pueden hacer sobre una única tabla, o sea los “joins” hay que implementarlos a mano.
Ejemplo de como implementar un “join”:
Tablas en las cuales existen atributos de tipo VarChar en el modelo 1 Dim myConn As New ADODB.Connection
Dim Table1 As New ADODB.Recordset Dim Table2 As New ADODB.Recordset Dim sentencia As String
' Apertura de la KB
myConn.Open ("Provider=GXPublic.GXPublic.1;Data Source=C:\ModeloPrueba") ' Se indica a quien pertenece los recordset
Table1.ActiveConnection = myConn Table2.ActiveConnection = myConn
'Se buscan los atributos de tipo Varchar del modelo 1
Table1.Open ("SELECT * FROM Attribute WHERE MDLID = 1 and AttTyp = 13") If Not Table1.EOF Then
Table1.MoveFirst
'Se recorre los registros resultado de la consulta select Do While Not Table1.EOF
'Para cada AttId se busca en la tabla TBLID en que tablas se encuentra sentencia = "SELECT * FROM TblAtt where MDLID = 1 and AttId = " + Str(Table1.Fields("ATTID"))
Table2.Open (sentencia)
If Not Table2.EOF Then
Table2.MoveFirst
'Se recorre los registros resultado de la sentencia select Do While Not Table2.EOF
MsgBox (Table2.Fields("TblId"))
Table2.MoveNext
Loop End If
Table2.Close Table1.MoveNext Loop
Table1.Close myConn.Close
End If