User Tools

Site Tools


relationmanager_overview.htm
Navigation:  ABC Library Reference > RelationManager >====== RelationManager Overview C6H0009.jpg ====== Previous pageReturn to chapter overviewNext page

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 &amp;= 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 &amp;= 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 )

relationmanager_overview.htm.txt · Last modified: 2021/04/15 15:57 by 127.0.0.1