Printer friendly version

Entendiendo AVR .NET's Memory File (ó Subfile en AVR 4.0) (Part 1)


AVR .NET's Memory File o Archivo de memoria es una interface de programación en RPG sobre .NET's System.Data.DataSet. Por adentro, lo que realmente sobresale en un Archivo de Memoria es .NET's System.Data.DataSet. El Archivo de Memoria sobresale este DataSet con su 'dataset' property. El DataSet es el sistema nervioso central de el Archivo de Memoria. Para entender el archivo de memoria usted debe entender el 'DataSet'.

El DataSet es realmente 'memoria cache' de los datos obtenidos de una fuente de datos (ej. archivo físico ó logico). En AVR.NET, esta fuente de datos es usualmente un AVR.NET memory file. El DataSet es un objeto 'padre' que consiste en uno o más objetos 'DataTable' y, opcionalmente, uno o más objetos 'DataRelation'. La mayor parte del tiempo, usted usará sólo una 'tabla' por 'dataset'. Cada objecto de una 'DataTable' consiste de un objeto 'DataColumn' y un 'DataRow'.

Figura 1. DataSet y sus objetos 'hijos' primarios

El DataSet es típicamente usado para popular un 'grid' (como un "subarchivo") en Windows ó aplicación de ASP.NET. Sin embargo, tiene muchos otros usos, incluyendo:
  • un súper canal de datos con el cual puede pasar data de una computadora a otra a traves de un método de un Servicio Web ó "Web Service"
  • una buena forma de "cache" data a traves de las páginas en una aplicación ASP.NET
  • una buena forma de "persistir" data para asegurar el comportamiento concurrente apropiado es enforzado para una optimización en los bloqueos de registros durante las actualizaciones de registros.
Para definir el esquema "schema" de un Archivo de memoria y su presentación, usted debe especificar:
  1. un "database name" en DBDesc (Nota este puede ser ya sea un database name como variable o el nombre de un objeto database (un DclDB) definido en otra parte del programa
  2. un archivo físico o lógico en la llave "FileDesc" y debe especificar
DclMemoryFile CustMem                             +
      DBDesc( "*Public/DG NET Local" )            +
      Prefix( Cust_ )                             + 
      FileDesc( "Examples/CMastNewL1" )           +          
      ImpOpen( *Yes )                             +
      RnmFmt( RCustMem ) 
Es muy importante recordar que el archivo usado para describir un archivo de memoria no es usado en tiempo de ejecución ("runtime"). Este arcivo es solamente usado en tiempo de compilación ("compile-time only"). No necesita ser distribuído. Así, la mejor práctica es crear una librería de archivos dedicados para el uso de definición de "datasets". Piensa de estos archivos como descripciones externas del contenido del "datagrid" (tienen el potencial a ser usados para muchas cosas que sólo el contenido del datagrid; pero porque esa es la razón principal de usar datasets, es una buena forma de pensar sobre estos archivos).

Muchos programadores de AVR han agonizado sobre esta necesidad de definir DataSets con archivos externos.VB y C# le permiten definir DataSets rápidamente. AVR.NET, porque respeta el modelo de RPG de archivos descritos externamente (donde los archivos deben ser conocidos en tiempo de compilación) debe tener la definición del DataSet en tiempo de compilación para poder leer y escribir al DataSet como si fuera un archivo RPG. Usted vera un truco más tarde en este artículo donde puede, si usted insiste, dinámicamente añadir columnas a una tabla de un archivo de memoria existente.

DataTables
El DataSet contiene una o más (usualmente una) DataTable. Para trabajar con la data en un DataSet, primero debe seleccionar (referenciar a) la tabla que usted quiere trabajar. Existen varias maneras de referenciar una tabla a un DataSet:

1. Usted puede usar la posición ordinal de la tabla ha como fue agregado ha el DataSet (Si solo tiene una tabla en el DataSet, esta es la manera más fácil):
DclFld Table     System.Data.DataTable
Table = CustMem.DataSet.Tables[ 0 ] 
2. Usted puede usar una referencia Directa en el programa al nombre del formato de archivo:
DclFld Table     System.Data.DataTable
Table = CustMem.DataSet.Tables[ "RCMMastL1" ]   
3. Usted puede usar una referencia Indirecta en el programa al nombre del formato de archivo:
DclFld Table      System.Data.DataTable
DclFld FormatName *String 

FormatName = CustMem.DataSet.GetFormatName( 0 ) 
Table = CustMem.DataSet.Tables[ FormatName ]   

Con una referencia de DataTable, usted puede ahora traversar el contenido de esta tabla.

DataColumns (Columnas de Datos) y DataRows (Líneas de Datos)
Cada DataTable está compuesta de una colección de objetos "DataColumn". Estas "DataColumns" definen la estructura del archivo (ej. sus campos, sus tipos y sus nombres). El contenido de cada DataTable están guardados en una colección de "DataRows".

Primero, conseguimos la referencia de la tabla. Con ella, ahora está listo para trabajar con sus líneas y columnas:
Table = CustMem.DataSet.Tables[ FormatName ]   
Usted puede leer una columna de un DataTable con:
ForEach Col Type( DataColumn ) Collection( Table.Columns ) 
    // 'Col' ahora contiene una referencia a una columna en la tabla
EndFor        
Usted puede leer una línea de un DataTable con:
ForEach Row Type( DataRow ) Collection( Table.Rows ) 
    // 'Row' contiene una referencia ha una línea en la tabla
EndFor        
Para traversar cada columna en cada línea, use esto:
ForEach Row Type( DataRow ) Collection( Table.Rows ) 
    ForEach Col Type( DataColumn ) Collection( Table.Columns ) 
        MsgBox Row[ Col.ColumnName ].ToString()
    EndFor        
EndFor		
Note que porque el DataSet es fuertemente escrito (eso es, el tipo de data de su columna ha sido establecido explicitamente), usted puede referenciar el valor de una columna de varias maneras:

— una referencia directa al nombre del campo:
    Row[ "CMMaster" ].ToString()
— una referencia indirecta al nombre del campo (usando la propiedad 'ColumnName' de un 'DataColumn':
    Row[ Col.ColumnName ].ToString()
— la posición ordinal del campo (el codigo debajo consigue el valor del 4to campo como fue definido en el archivo de datos):
    Row[ 3 ].ToString()
Recuerde que cuando usted trata de usar los valores de las columnas, usted necesitará exponerlas apropiadamente (éstas son 'parqueadas' en la columna como *Objetos).

No solo usted puede leer data de esta manera desde una tabla en un dataset, usted tambien puede cambiarla. Por ejemplo, para cambiar todos los nombres de clientes a mayúsculas, usted puede usar esto:
ForEach Row Type( DataRow ) Collection( Table.Rows ) 
    Row[ "CMName" ] = Row[ "CMName" ].ToString().ToUpper()
EndFor		
Encontrar una línea dada en un 'DataSet' por valor
Es posible leer una línea al azar en el DataSet. Actualmente, debemos ser más claros con el lenguaje --lo que estamos haciendo es encontrando una línea en la DataTable de un DataSet. Para encontrar una línea:

Para leer una línea al azar, primero debe establecer la estructura de la llave del DataTable. El código debajo muestra como hacerlo. Esto trabaja con llaves simples- o múltiples. Esto solo debe hacerse una vez por tabla. Una vez haya hecho esto, la estructura de la llave persiste siempre y cuando la tabla también.

BegSr EstablishCustMemKey      
    DclFld Table   System.Data.DataTable

    Table = CustMem.DataSet.Tables[ 0 ]   

    DclArray KeyStructure Type( DataColumn ) Rank( 1 ) 
    DclArray KeyValue     Type( *Object )    Rank( 1 )         

    KeyStructure      = *New DataColumn[ 1 ]       
    KeyStructure[ 0 ] = Table.Columns[ "CMCustNo" ] 
    Table.PrimaryKey  = KeyStructure
EndSr         
Ahora, escriba una funcción "chain" a la tabla. Esta función puede tomar los parámetros que desee en su llave como campos. De nuevo, en este caso, uno.

BegFunc ChainMemCust Type( System.Data.DataRow ) 
    DclSrParm CustNo Type( *Integer4 ) 

    DclFld Table          System.Data.DataTable     
    DclArray KeyValue     Type( *Object )  Dim( 1 ) 
    DclFld Row            System.Data.DataRow

    Table = CustMem.DataSet.Tables[ 0 ]   

    KeyValue[ 0 ] = CustNo

    Row = Table.Rows.Find( KeyValue ) 

    LeaveSr Row 
EndFunc 
Entonces llámelo de esta manera:

    DclFld Row System.Data.DataRow

    Row = ChainMemCust( 200 ) 
    If ( Row = *Nothing ) 
        MsgBox "Row not found"
    Else        
        MsgBox Row[ "CMName" ].ToString() 
    EndIf
Añadiendo y Llenando Dinámicamente un campo a un Archivo de Memoria
Como una mejor práctica, recomendamos usar un archivo físico para describir el DataTable de un DataSet. Sin embargo, existe una manera, sin mucha dificultad, de agregar columnas a un archivo de memoria previamente definido.

1. Añadir una columna a una tabla del archivo de memoria
Use el método Añadir (Add) dentro de la colección "Columns" para añadir una columna a la tabla. Esto solo necesita hacerse por la duración del objeto tabla .

CustMem.DataSet.Tables[ 0 ].Columns.Add( "EMail", *TypeOf( *String ) )
Si usted necesita escribir una columna *Zoned o *Packed, escríbela como System.Decimal. Por ejemplo, para agregar una columna que tendrá un valor "packed":

CustMem.DataSet.Tables[ 0 ].Columns.Add( "HourlyRate", *TypeOf( System.Decimal ) )
2. Escribe la data a la nueva columna
La operación WRITE de AVR no escribirá la data a la nueva columna añadida. Para escribir data en ella, priemero necesita hacer la referencia a la línea que quiere actualizar, así después podrá actualizar la columna.

// Before your write loop, declare an variable typed as the DataRow class.

DclFld Row    DataRow 
DclFld Table  System.Data.DataTable  

// Hacer la referencia a la tabla.
Table = CustMem.DataSet.Tables[ 0 ]

// Iniciar "loop" para escribir registros al archivo de memoria (para un datagrid, por ejemplo). 

    // Asignar campos definidos por el "FILEDESC" parameter del archivo de memoria aquí.
    Write CustMem

    // Hacer referencia a la última línea en una tabla (la línea que usted ha escrito).
    // Alternativamente, si usted actualiza data "ramdomly", puede usar las técnicas arriba 
    // mencionadas para hacer una referencia a una línea vía una llave.
    Row = Table.Rows[ Table.Rows.Count - 1 ]		    

    // Con la referencia a la línea que acaba de añadir, manualmente llene los campos
    // que usted ha añadido aquí.

    // Consiga el valor que desea escribir en la columna añadida. En este
    // caso estamos encadenando un archivo secundario por el campo "EmailAddress".
    Chain EmailList Key( CustCMCustNo ) // Obtiene "EmailAddress" para usted

    // llenar el campo Email.
    Row.Item[ "Email" ] = EmailAddress
// End loop 
Esté pendiente por la parte 2 para cubrir más sobre el archivo de memoria.

Docid=294     Created on: 09-02-2004     Last updated on: 09-13-2004
(c) Copyright 2004 ASNA. All rights reserved.