Navigation: ABC Library Reference > RelationManager >====== RelationManager Overview ====== | |
The RelationManager class declares a relation manager object that does the following:
·Consistently and flexibly defines relationships between files–the relationships need not be defined in a data dictionary; they may be defined directly (dynamically) to the relation manager object.
·Reliably enforces discrete specified levels of referential integrity (RI) constraints between the related files–the RI constraints need not be defined in a data dictionary; they may be defined directly (dynamically) to the relation manager object.
·Conveniently forwards appropriate file commands to related files–for example, when a relation manager object opens its primary file, it also opens any related files.
The RelationManager class provides “setup” methods that let you describe the file relationships, their linking fields, and their associated RI constraints; plus other methods to perform the cascadable or constrainable database operations such as open, change, delete, and close.
Relation Manager Concepts and Conventions
Cascading Commands and Referential Constraints
You can fully describe a set of file relationships with a series of RelationManager objects–one RelationManager object for each file. Each RelationManager object defines the relationships between its primary file and any files directly related to the primary file. However, each RelationManager object also knows about its related files' RelationManager objects, so indirectly, it knows about those secondary relationships too.
For example, consider three related files: Customer <;→> Order <;→> Item, where <;→> indicates a one:many relationship. The RelationManager object for the Customer file knows about the relationship between Customer and Order, but it also knows about the Order file's RelationManager object, so indirectly, it knows about the relationship between Order and Item too.
The benefit of this chain of RelationManager awareness, is that you can issue a file command such as open or close to any one of the RelationManager objects and it forwards the command up and down the chain of related files; and for deletes or changes, it enforces any relational integrity constraints up and down the chain of related files.
Me and Him
Some of the RelationManager methods refer to its primary file as “MyFile” or “Me” and its related files as “HisFile” or “Him.” See Relation Manager Properties for more information.
Left and Right (and Buffer)
Some of the RelationManager methods refer to its primary file record buffer as “Left,” the associated queue buffer as “Right” and the associated save area for the record as “Buffer.” See BufferedPairsClass and FieldPairsClass for more information.
RelationManager ABC Template Implementation
The ABC Templates derive a class from the RelationManager class for each file the application processes. The derived classes are called Hide:Relate:filename, but may be referenced as Relate:filename. These derived classes and their methods are declared and implemented 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 enforce the file relationships and referential integrity constraints specified in the data dictionary.
The ABC Templates generate housekeeping procedures to initialize and shut down the RelationManager objects. The procedures are DctInit and DctKill. They are generated into the appnaBC.CLW file.
The derived RelationManager classes are configurable with the Global Properties dialog. See Template Overview–File Control Options and Classes Options for more information.
RelationManager Relationship to Other Application Builder Classes
FileManager and BufferedPairsClass
The RelationManager relies on both the FileManager and the BufferedPairsClass to do much of its work. Therefore, if your program instantiates the RelationManager it must also instantiate the FileManager and the BufferedPairsClass. Much of this is automatic when you INCLUDE the RelationManager header (ABFILE.INC) in your program's data section. See the Conceptual Example and see File Manager Class and Field Pairs Classes for more information.
ViewManager
Perhaps more significantly, the RelationManager serves as the foundation or “errand boy” of the ViewManager. If your program instantiates the ViewManager it must also instantiate the RelationManager. See View Manager Class for more information.
RelationManager Source Files
The RelationManager source code is installed by default to the Clarion \LIBSRC folder. The RelationManager source code and its respective components are contained in:
ABFILE.INC | RelationManager declarations | |
ABFILE.CLW | RelationManager method definitions |
RelationManager Conceptual Example
The following example shows a typical sequence of statements to declare, instantiate, initialize, use, and terminate some RelationManager objects.
This example uses the RelationManager class to cascade new key values from parent file records to the corresponding child file records.
PROGRAM
INCLUDE('ABFILE.INC')
INCLUDE('ABREPORT.INC')
MAP
END
CUSTOMER FILE,DRIVER('TOPSPEED'),NAME('CUSTOMER'),PRE(CUS),BINDABLE,CREATE,THREAD
BYNUMBER KEY(CUS:CUSTNO),NOCASE,OPT,PRIMARY
Record RECORD,PRE()
CUSTNO LONG
NAME STRING(30)
ZIP DECIMAL(5)
END
END
PHONES FILE,DRIVER('TOPSPEED'),NAME('PHONES'),PRE(PHO),BINDABLE,CREATE,THREAD
BYCUSTOMER KEY(PHO:CUSTNO,PHO:PHONE),DUP,NOCASE,OPT
Record RECORD,PRE()
CUSTNO LONG
PHONE STRING(20)
TYPE STRING(8)
END
END
GlobalErrors ErrorClass
Access:CUSTOMER CLASS(FileManager)
Init PROCEDURE
END
Relate:CUSTOMER CLASS(RelationManager)
Init PROCEDURE
END
Access:PHONES CLASS(FileManager)
Init PROCEDURE
END
Relate:PHONES CLASS(RelationManager)
Init PROCEDURE
END
RecordsPerCycle LONG(25)
StartOfCycle LONG,AUTO
PercentProgress BYTE
ProgressMgr StepLongClass
CustView VIEW(CUSTOMER)
END
Process ProcessClass
Progress:Bar BYTE
ProgressWindow WINDOW('Processing…'),AT(,,142,59),CENTER,TIMER(1),GRAY,DOUBLE
PROGRESS,USE(Progress:Bar),AT(15,15,111,12),RANGE(0,100)
STRING(),AT(0,3,141,10),USE(?Progress:UserString),CENTER
STRING(
),AT(0,30,141,10),USE(?Progress:Text),CENTER
BUTTON('Cancel'),AT(45,42,50,15),USE(?Progress:Cancel)
END
CODE
GlobalErrors.Init
Relate:CUSTOMER.Init
Relate:PHONES.Init
ProgressMgr.Init(ScrollSort:AllowNumeric)
Process.Init(CustView,Relate:CUSTOMER,|
?Progress:Text,Progress:Bar,|
ProgressMgr,CUS:CUSTNO)
Process.AddSortOrder( CUS:BYNUMBER )
Relate:CUSTOMER.Open
OPEN(ProgressWindow)
?Progress:Text{Prop:Text} = '0% Completed'
ACCEPT
CASE EVENT()
OF Event:OpenWindow
Process.Reset
IF Process.Next()
POST(Event:CloseWindow)
CYCLE
END
OF Event:Timer
StartOfCycle=Process.RecordsProcessed
LOOP WHILE Process.RecordsProcessed-StartOfCycle<;RecordsPerCycle
CUS:CUSTNO+=100 !change parent key value
IF Relate:CUSTOMER.Update() !cascade change to children
BREAK
END
CASE Process.Next()
OF Level:Notify
?Progress:Text{Prop:Text} = 'Process Completed'
DISPLAY(?Progress:Text)
POST(EVENT:CloseWindow)
BREAK
OF Level:Fatal
POST(EVENT:CloseWindow)
BREAK
END
END
END
CASE FIELD()
OF ?Progress:Cancel
CASE Event()
OF Event:Accepted
POST(Event:CloseWindow)
END
END
END
ProgressMgr.Kill
Relate:CUSTOMER.Close
Relate:CUSTOMER.Kill
Relate:PHONES.Kill
GlobalErrors.Kill
Access:CUSTOMER.Init PROCEDURE
CODE
PARENT.Init(Customer, GlobalErrors)
SELF.FileNameValue = 'CUSTOMER'
SELF.Buffer &= CUS:Record
SELF.AddKey(CUS:BYNUMBER,'CUS:BYNUMBER',1)
Relate:CUSTOMER.Init PROCEDURE
CODE
Access:CUSTOMER.Init
PARENT.Init(Access:CUSTOMER,1)
SELF.AddRelation(Relate:PHONES,RI:Cascade,RI:Restrict,PHO:BYCUSTOMER)
SELF.AddRelationLink(CUS:CUSTNO,PHO:CUSTNO)
Access:PHONES.Init PROCEDURE
CODE
PARENT.Init(Phones, GlobalErrors)
SELF.FileNameValue = 'PHONES'
SELF.Buffer &= PHO:Record
SELF.AddKey(PHO:BYCUSTOMER,'PHO:BYCUSTOMER')
Relate:PHONES.Init PROCEDURE
CODE
Access:PHONES.Init
PARENT.Init(Access:PHONES,1)
SELF.AddRelation( Relate:CUSTOMER )