company logo

Creating Handle hierarchy

For getting access to database details one may open a hierarchical structure of database access objects:

  • [ Application ]
  • [ Client ]
  • Dictionary
  • Database
  • [ ObjectSpace ]
  • Property
  • Value

Each of those access handles allows to manage any number of subordinated access handles, i.e. one may several databases for the same dictionary etc. Handle hierarchies correspond to physical application resources, which are managed by the resource specific objects referenced by the handle:

Application - Global application object

Client - Server connection
Dictionary - Resource database
Database - Database
DBObject - Universe/transaction
Property - Instance/collection
Value - Value

Usually, the application has to create a dictionary, database and property handle in order to run 'normal' applications. More complicate applications (e.g. with multiple server connections) require explicitly defined application clients. Complex database applications may also store data in different object spaces, which requires explicitly opened object space handles.

The example below shows how to get access to persons in the sample database (simple case).

// creating a simple access hierarchy

... fragment ( ) {

  Dictionary dict;

  Database   db;

// Applixation::mainClient is used as default client

  dict.open("Sample.dev", Read, true);

  db.open(dict, "Sample.dat", Read, true);  

// object space is the database (root object space)

  Property   persons(db, "Person::Persons", Read);

  Value      name(persons,"name");

  

  while ( persons.next() )

    Application::output(name.toString());

}

Constructing and opening access handles

Usually, access handles are created as empty access handles (constructor without parameters) and opened later on explicitly calling the corresponding open() function.

For convenience, Property and Value provide enhanced constructors, which implicitly call the appropriate open function.

In order to check, whether an access handle has been opened or not, all access handle classes provide an isValid() function, which returns true, in case the handle has been opened successfully.

  Dictionary     dict;

  Database       db;

  

  dict.open("c:/ODABA/Sample/Sample.dev");

  db.open(dict,"c:/ODABA/Sample/Sample.dat");

// global extent

  Property  company(db,"Company",Read);

// namespace extent

  Property  person(db,"Person::Persons",Read); // implicit open() call

  Value     name(person,"name");      // implicit open() call

Using handles in a handle hierarchy

Once, a handle hierarchy has been defined, handles can be used in many different ways for accessing data. Usually, dictionary and database will not change while running an application, but property handle and value hierarchies might become rather complex.

In order to access properties and values, property and value handle have to be in a certain state. E.g. in order to read data for children of a person, an instance has to be selected in the person property handle. In order to read or update a value for a child, the child has to be selected. When changing the selection state in the person property handle, the children property handle automatically becomes unselected and values for children are not accessible until a new instance has been selected for the person and the children property handle.

...  fragment ( Database &rDatabase ) {

  Property     persons(rDatabase,"Person::Persons",Update);

// parent property (persons) has to be opened, but not selected

  Property     children(person,"children");

// parent property (children) has to be opened, but not selected

  Value        name(children,"name");

  

  while ( person.next() )     // selects a person

    while ( children.next() ) // selects a child

      Application::output(name.toString()); // prints name for selected child

}

Destroying and closing handles

Similar to create and open access handles, they will be closed automatically when destroying an access handle. One may, however, also explicitly call the close() function.

All access handle objects have got a reference count. Thus, creating a handle copy (e.g. using the copy constructor) just creates a reference to the same access node. Thus, destroying or closing an access handle not necessarily deletes the access node.

When closing the last reference to an access node, all subordinated access nodes will be deleted and the access handles referring to it will be closed. E.g. when closing a database access node, all subordinated object space and property handles will be closed. Property handles opened with copyCursor() are also closed, when the original access node (cursor) will be destroyed.

In order to avoid inconsistent database states, all updates are stored before deleting an access node (i.e. closing the last access handle referring to it).