AVR for .NET's memory file is an RPG programming interface over .NET's
System.Data.DataSet. Under the covers, what really lurks in a memory file is .NET's
System.Data.DataSet. The memory file surfaces this
DataSet with its dataset property. The
DataSet is the central nervous system of the memory file. To understand the memory file you need to understand the
DataSet. When you write to and read from a memory file, the memory file's
DataSet property is where all that writing and reading is really taking place.
DataSet is an in-memory cache of data retrieved from a data source. The
DataSet is a parent object that consists of one more
DataTable objects. For most purposes, especially when using a memory file, you'll only have one table per dataset. Each
DataTable object consists of
Figure 1. The DataSet and its inner members.
The memory file
AVR's memory file is an in-memory file generally used as a temporary data store. Rows are "written" (in quotations because rows are written to memory, not disk) to memory files, usually to later be bound to a .NET user interface element.
Beware that a memory file stores its contents in memory, never on disk. Be mindful of how many rows you write to a memory file. While it is surprising how many rows .NET can sustain in memory, don't get carried away. Not only would lots of rows tax memory, but they would also offer a larger payload across the network. No user wants to to wait on 5,000 rows being rendered in the browser!
Let's take a look at two ways to declare a memory file:
Create a memory file that duplicates all of the fields in a given file:
DclMemoryFile MemFile + DBDesc("*Public/DG Net Local") + FileDesc("Examples/CMastNewL1") + RnmFmt(MemFileR)
The memory file above contains all of the columns in the
Examples/CMastNewL1 file. Memory files are using used along with a corresponding
DclDiskFile of the same data file, so it's usually necessary to rename the memory file's format.
Create a program-described memory file:
DclMemoryFile MemFile ImpOpen(*Yes) DclRecordFormat Customers DclRecordFld Customer_CMCustNo Type(*Packed) Len(9,0) DclRecordFld Customer_CMName Type(*Char) Len(40)
The memory file above creates a memory file with two fields. Program-described memory files are useful when you don't need every column in a file. A program-described memory file's format name is explicitly provided with the required
DclRecordFormat operation code.
The discussion applies to either way of defining a memory file.
Populating a memory file
The code below writes up to 16 rows to a memory file, after each read of a record from the
DclDB DGDB DBName("*Public/DG Net Local") DclDiskFile Customer + Type(*Input) + Org(*Indexed) + Prefix(Customer_) + File("examples/cmastnewl2") + DB(DGDB) + ImpOpen(*No) DclMemoryFile MemFile ImpOpen(*Yes) DclRecordFormat Customers DclRecordFld Customer_CMCustNo Type(*Packed) Len(9,0) DclRecordFld Customer_CMName Type(*Char) Len(40) ... Do FromVal(1) ToVal(16) Read Customer If Customer.IsEof() Leave EndIf Write MemFile EndDo
The result of the code above is that the
DataTable property is populated with the rows read from the
Customer file. Direct access to the memory file's
DataSet is available with this code:
DclFld ds Type(System.Data.DataSet) ds = MemFile.DataSet
Recall that the
DataSet can have more than one
DataTable (although used with AVR it rarely, if ever, does). These
DataTables are available through the
Tables collection. The code below fetches the zeroth (the only)
DataTable in the
DclFld dt Type(System.Data.DataTable) dt = MemFile.DataSet.Tables
DataColumns and DataRows
DataTable comprises a collection of
DataColumn objects. These
DataColumns define the file's layout (i.e., its field names, their types, and their values). The contents of each
DataTable are stored in a collection of
First, get the table reference. With it, you're ready to work with the table's rows and columns:
dt = MemFile.DataSet.Tables
ForEach Col Type(DataColumn) Collection(dt.Columns) // Col now contains a reference to a column in the table EndFor
ForEach Row Type(DataRow) Collection(dt.Rows) // Row contains a reference to a row in the table EndFor
Putting all that together, the code be;pw loads 16 rows into the memory file and then shows each field value in each
DataRow, fetching the values out by field name:
DclDB DGDB DBName("*Public/DG Net Local") DclDiskFile Customer + Type(*Input) + Org(*Indexed) + File("examples/cmastnewl2") + DB(DGDB) + ImpOpen(*No) DclMemoryFile MemFile + DBDesc("*Public/DG Net Local") + FileDesc("Examples/CMastNewL1") + RnmFmt(MemFileR) BegSr Run Access(*Public) DclFld FieldNameList Type(StringCollection) Connect DGDB Open Customer WriteRowsToMemoryFile() FieldNameList = GetFieldNameList() ShowFieldValues(FieldNameList) Close *All Disconnect DGDB EndSr BegSr WriteRowsToMemoryFile Do FromVal(1) ToVal(16) Read Customer If Customer.IsEof() Leave EndIf Write MemFile EndDo EndSr BegFunc GetFieldNameList Type(StringCollection) DclFld dt Type(DataTable) DclFld FieldNameList Type(StringCollection) New() dt = MemFile.DataSet.Tables // Iterate each column adding its field name to the collection. ForEach Col Type(DataColumn) Collection(dt.Columns) FieldNameList.Add(col.ColumnName.ToString()) EndFor LeaveSr FieldNameList EndFunc BegSr ShowFieldValues DclSrParm FieldNameList Type(StringCollection) DclFld dt Type(DataTable) dt = MemFile.DataSet.Tables // Iterate each data row. ForEach dr Type(DataRow) Collection(dt.Rows) // Show the value for each field in the row. ForEach FieldName Type(*String) Collection(FieldNameList) Console.WriteLine(dr[FieldName].ToString()) // Note that field values are also assignable. // Assuming 'FieldName is a string type, you could do this. // dr[FieldName] = 'xyz' EndFor EndFor EndSr
DataSet is looked down on by purists, there is a lot AVR can do with it. Spend some time seeing what it can do for you.