Navigation: ABC Library Reference > FileManager >====== FileManager Overview ====== | |
The FileManager class declares a file manager that consistently and flexibly handles all the routine database operations for a given file. The file manager provides “setup” methods that let you describe the file and it's keys, as well as other methods to open, read, write, and close the file.
The file manager automatically handles autoincrementing keys, and, as implemented by the ABC Templates, handles some of the validity checks specified in the Clarion data dictionary, and some of the file handling settings specified in the data dictionary or application generator. However, even if you don't use the data dictionary, the application generator, or if you don't specify validity checks in your dictionary, the file manager can still competently and efficiently handle routine database operations for your files.
The FileManager class handles individual files; it does not handle referential integrity (RI) between related files. The RelationManager class enforces RI between related files.
Dual Approach to Database Operations
The FileManager methods that do standard database operations come in two versions–the plain (or interactive) version and the “Try” (or silent) version.
Interactive Database Operations
When any of these methods are called (Open, Fetch, Next, Previous, Insert, and Update), they may take several approaches and several attempts to complete the requested operation–including issuing error messages where appropriate. They may solicit information from the end user in order to proceed with the requested task. They may even terminate the application under sufficient provocation. This means the programmer can rely on the fact that if the method returned, it worked.
Silent Database Operations
When any of these methods are prepended with “Try” (TryOpen, TryFetch, TryNext, TryPrevious, TryInsert, and TryUpdate), the method makes a single attempt to complete the requested operation, then returns a success or failure indicator to the calling procedure for it to handle accordingly.
FileManager Relationship to Other Application Builder Classes
The FileManager relies on the ErrorClass for most of its error handling. Therefore, if your program instantiates the FileManager it must also instantiate the ErrorClass. See Error Class for more information.
Perhaps more significantly, the FileManager serves as the foundation or “errand boy” of the RelationManager. If your program instantiates the RelationManager it must also instantiate the FileManager. See Relation Manager Class for more information.
FileManager and Threaded Files
FileManager objects are designed to support multiple execution threads in a way that Clarion developers will recognize. That is, several MDI procedures may access the same file at the same time, with each procedure maintaining its own file buffer and file positioning information, so there is no conflict or confusion between the procedures.
To accomplish this desirable state of independence among several MDI procedures, you only need to add the THREAD attribute to your file declaration (see the Language Reference for more information), then instantiate a single global FileManager object for each file. This global object automatically handles multiple execution threads, so you can use it within each procedure that accesses the file. The ABC Templates generate exactly this type of code for files with the THREAD attribute.
When you want to access a file with a single shared buffer from multiple execution threads, you simply omit the THREAD attribute from the file declaration and, again, instantiate a global file-specific FileManager object within the program. This lets all your program's procedures access the file with a single shared record buffer and a single set of positioning information.
FileManager ABC Template Implementation
There are several important points to note regarding the ABC Template implementation of the FileManager class.
First, the ABC Templates derive a class from the FileManager class for each file the application processes. The derived classes are called Hide:Access:filename, but may be referenced as Access:filename. These derived classes and their methods are declared in the generated appnaBC0.CLW through appnaBC9.CLW files (depending on how many files your application uses). The derived class methods are specific to the file being managed, and they implement many of the file properties specified in the data dictionary such as access modes, keys, field validation and initialization, etc.
Second, the ABC Templates generate housekeeping procedures to initialize and shut down the FileManager objects. The procedures are DctInit and DctKill. These are generated into the appnaBC.CLW file.
Third, the derived FileManager classes are configurable with the Global Properties dialog. See Global Properties–File Control Options and Classes Options for more information.
Finally, the ABC Templates also derive a RelationManager for each file. These objects are called Hide:Relate:filename, but may be referenced as Relate:filename. The template generated code seldom calls the derived FileManager methods directly. Instead, it calls a RelationManager method that echoes the command to the appropriate (related files') FileManager methods. See Relation Manager for more information on the RelationManager class.
FileManager Source Files
The FileManager source code is installed by default to the Clarion \LIBSRC folder. The specific FileManager source code and their respective components are contained in:
ABFILE.INC | FileManager declarations | |
ABFILE.CLW | FileManager method definitions |
FileManager Conceptual Example
The following example shows a typical sequence of statements to declare, instantiate, initialize, use, and terminate a FileManager object.
This example uses the FileManager to insert a valid record with an auto-incrementing key.
PROGRAM
INCLUDE('ABFILE.INC') !declare FileManager class
MAP !program map
END
GlobalErrors ErrorClass !declare GlobalErrors object
Access:Client CLASS(FileManager) !derive Access:Client object
Init PROCEDURE !initialize Access:File object
PrimeRecord PROCEDURE,BYTE,PROC,VIRTUAL !prime new record (autoinc)
ValidateField PROCEDURE(UNSIGNED Id),BYTE,VIRTUAL !validate a field
ValidateRecord PROCEDURE(<;*UNSIGNED Id>),BYTE,VIRTUAL !validate all fields
END
Client FILE,DRIVER('TOPSPEED'),PRE(CLI),CREATE,BINDABLE,THREAD
IDKey KEY(CLI:ID),NOCASE,OPT,PRIMARY
NameKey KEY(CLI:Name),DUP,NOCASE
Record RECORD,PRE()
ID LONG
Name STRING(20)
StateCode STRING(2)
END
END
InsertWindow WINDOW('Add a new Client'),AT(,,159,73),IMM,SYSTEM,GRAY
PROMPT('&Name:'),AT(8,20),USE(?CLI:Name:Prompt)
ENTRY(@s20),AT(61,20,84,10),USE(CLI:Name),MSG('Client Name'),REQ
PROMPT('State Code:'),AT(8,34),USE(?CLI:StateCode:Prompt)
ENTRY(@s2),AT(61,34,40,10),USE(CLI:StateCode),MSG('State Code')
BUTTON('OK'),AT(12,53,45,14),USE(?OK),DEFAULT
END
CODE
GlobalErrors.Init !initialize GlobalErrors object
Access:Client.Init !initial Access:Client object
Access:Client.Open !open the Client file
IF Access:Client.PrimeRecord() !prime Client record (autoinc)
POST(Event:CloseWindow) !if prime fails, close down
END
OPEN(InsertWindow)
ACCEPT
CASE FIELD()
OF ?OK
IF EVENT() = Event:Accepted !on OK button
IF Access:Client.Insert() = Level:Benign !add the new Client record
POST(Event:CloseWindow) !if add succeeds, close down
ELSE !if add fails
SELECT(?CLI:Name:Prompt) !select client name field
CYCLE !and start over
END
END
OF ?CLI:StateCode !on StateCode field
IF EVENT() = EVENT:Accepted
IF Access:Client.ValidateField(3) !validate the StateCode (3rd) field
SELECT(?CLI:StateCode) !if invalid, select StateCode field
CYCLE !and start over
END
END
END
Access:Client.Close !close the Client file
Access:Client.Kill !shut down the Access:Client object
GlobalErrors.Kill !shut down the GlobalErrors object
RETURN
Access:Client.Init PROCEDURE
CODE
PARENT.Init(Client, GlobalErrors) !call the base class Init method
SELF.FileNameValue = 'Client' !set the file name
SELF.Buffer &= CLI:Record !point Access:Client to Client buffer
SELF.AddKey(CLI:IDKey,'Client ID',1) !describe the primary autoinc key
SELF.AddKey(CLI:NameKey,'Client Name') !describe another key
Access:Client.PrimeRecord PROCEDURE !called by base class Insert method
Result BYTE,AUTO
CODE
Result = PARENT.PrimeRecord() !call base class PrimeRecord method
CLI:StateCode = 'FL' !default statecode to Florida
RETURN Result
Access:Client.ValidateField PROCEDURE(UNSIGNED Id)!called by base class ValidateFields
CODE !and by this program too
IF ID = 3 !validate the statecode (3rd) field
GlobalErrors.SetField('StateCode') !set field in case of error
IF ~CLI:StateCode !if statecode is blank
RETURN SELF.Throw(Msg:FieldNotInList) !pass error to error handler
END
END
RETURN Level:Benign
Access:Client.ValidateRecord PROCEDURE(<;*UNSIGNED F>)!called by base class Insert
CODE
RETURN SELF.ValidateFields(1,3,F) !validate all 3 fields